Commit a66fcd8d authored by Cedric Roux's avatar Cedric Roux

Use TUN device for NAS for the UE instead of ue_ip.ko

This work is based on work by NTT.

To use the code, do:
./build_oai --oaisim --ue-nas-use-tun -t ETHERNET -c

This commit only handles oaisim in S1 mode.

We won't handle noS1 mode.
parent 4aa8ac6d
...@@ -242,6 +242,7 @@ add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace") ...@@ -242,6 +242,7 @@ add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace")
add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace") add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace")
add_boolean_option(DISABLE_LOG_X False "Deactivate all LOG_* macros") add_boolean_option(DISABLE_LOG_X False "Deactivate all LOG_* macros")
add_boolean_option(USRP_REC_PLAY False "Enable USRP record playback mode") add_boolean_option(USRP_REC_PLAY False "Enable USRP record playback mode")
add_boolean_option(UE_NAS_USE_TUN False "Enable UE NAS TUN device instead of ue_ip.ko")
add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering") add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
......
...@@ -67,6 +67,7 @@ UE_TIMING_TRACE="False" ...@@ -67,6 +67,7 @@ UE_TIMING_TRACE="False"
DISABLE_LOG_X="False" DISABLE_LOG_X="False"
USRP_REC_PLAY="False" USRP_REC_PLAY="False"
BUILD_ECLIPSE=0 BUILD_ECLIPSE=0
UE_NAS_USE_TUN="False"
trap handle_ctrl_c INT trap handle_ctrl_c INT
function print_help() { function print_help() {
...@@ -156,6 +157,8 @@ Options ...@@ -156,6 +157,8 @@ Options
Build eclipse project files. Paths are auto corrected by fixprj.sh Build eclipse project files. Paths are auto corrected by fixprj.sh
--usrp-recplay --usrp-recplay
Build for I/Q record-playback modes Build for I/Q record-playback modes
--ue-nas-use-tun
Use TUN devices for the UEs instead of ue_ip.ko
Usage (first build): Usage (first build):
oaisim (eNB + UE): ./build_oai -I --oaisim -x --install-system-files oaisim (eNB + UE): ./build_oai -I --oaisim -x --install-system-files
Eurecom EXMIMO + COTS UE : ./build_oai -I --eNB -x --install-system-files Eurecom EXMIMO + COTS UE : ./build_oai -I --eNB -x --install-system-files
...@@ -347,6 +350,10 @@ function main() { ...@@ -347,6 +350,10 @@ function main() {
USRP_REC_PLAY="True" USRP_REC_PLAY="True"
echo_info "Enabling USRP record playback mode" echo_info "Enabling USRP record playback mode"
shift 1;; shift 1;;
--ue-nas-use-tun)
UE_NAS_USE_TUN="True"
echo_info "Enabling UE NAS TUN device usage instead of ue_ip.ko"
shift 1;;
-h | --help) -h | --help)
print_help print_help
exit 1;; exit 1;;
...@@ -696,6 +703,7 @@ function main() { ...@@ -696,6 +703,7 @@ function main() {
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
echo "set ( UE_NAS_USE_TUN $UE_NAS_USE_TUN )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
[ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build [ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build
mkdir -p $DIR/$oaisim_build_dir/build mkdir -p $DIR/$oaisim_build_dir/build
......
...@@ -39,6 +39,13 @@ ...@@ -39,6 +39,13 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include "platform_constants.h" #include "platform_constants.h"
#ifdef UE_NAS_USE_TUN
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include "openairinterface5g_limits.h"
#endif
char nl_rx_buf[NL_MAX_PAYLOAD]; char nl_rx_buf[NL_MAX_PAYLOAD];
...@@ -47,12 +54,121 @@ struct nlmsghdr *nas_nlh_tx = NULL; ...@@ -47,12 +54,121 @@ struct nlmsghdr *nas_nlh_tx = NULL;
struct nlmsghdr *nas_nlh_rx = NULL; struct nlmsghdr *nas_nlh_rx = NULL;
struct iovec nas_iov_tx; struct iovec nas_iov_tx;
struct iovec nas_iov_rx = {nl_rx_buf, sizeof(nl_rx_buf)}; struct iovec nas_iov_rx = {nl_rx_buf, sizeof(nl_rx_buf)};
#ifdef UE_NAS_USE_TUN
int nas_sock_fd[NUMBER_OF_UE_MAX];
#else
int nas_sock_fd; int nas_sock_fd;
#endif
struct msghdr nas_msg_tx; struct msghdr nas_msg_tx;
struct msghdr nas_msg_rx; struct msghdr nas_msg_rx;
#define GRAAL_NETLINK_ID 31 #define GRAAL_NETLINK_ID 31
#ifdef UE_NAS_USE_TUN
static int tun_alloc(char *dev)
{
struct ifreq ifr;
int fd, err;
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
printf("[TUN] failed to open /dev/net/tun\n");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
strcpy(dev, ifr.ifr_name);
return fd;
}
int netlink_init(void)
{
int i;
int ret;
char ifname[64];
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
sprintf(ifname, "oip%d", i+1);
nas_sock_fd[i] = tun_alloc(ifname);
if (nas_sock_fd[i] == -1) {
printf("[NETLINK] Error opening socket %d (%d:%s)\n",nas_sock_fd[i],errno, strerror(errno));
#if defined(LINK_ENB_PDCP_TO_IP_DRIVER)
exit(1);
#endif
}
printf("[NETLINK]Opened socket with fd %d\n",nas_sock_fd[i]);
#if !defined(PDCP_USE_NETLINK_QUEUES)
ret = fcntl(nas_sock_fd[i],F_SETFL,O_NONBLOCK);
if (ret == -1) {
printf("[NETLINK] Error fcntl (%d:%s)\n",errno, strerror(errno));
#if defined(LINK_ENB_PDCP_TO_IP_DRIVER)
exit(1);
#endif
}
#endif
memset(&nas_src_addr, 0, sizeof(nas_src_addr));
nas_src_addr.nl_family = AF_NETLINK;
nas_src_addr.nl_pid = 1;//getpid(); /* self pid */
nas_src_addr.nl_groups = 0; /* not in mcast groups */
ret = bind(nas_sock_fd[i], (struct sockaddr*)&nas_src_addr, sizeof(nas_src_addr));
memset(&nas_dest_addr, 0, sizeof(nas_dest_addr));
nas_dest_addr.nl_family = AF_NETLINK;
nas_dest_addr.nl_pid = 0; /* For Linux Kernel */
nas_dest_addr.nl_groups = 0; /* unicast */
// TX PART
nas_nlh_tx=(struct nlmsghdr *)malloc(NLMSG_SPACE(NL_MAX_PAYLOAD));
memset(nas_nlh_tx, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
/* Fill the netlink message header */
nas_nlh_tx->nlmsg_len = NLMSG_SPACE(NL_MAX_PAYLOAD);
nas_nlh_tx->nlmsg_pid = 1;//getpid(); /* self pid */
nas_nlh_tx->nlmsg_flags = 0;
nas_iov_tx.iov_base = (void *)nas_nlh_tx;
nas_iov_tx.iov_len = nas_nlh_tx->nlmsg_len;
memset(&nas_msg_tx,0,sizeof(nas_msg_tx));
nas_msg_tx.msg_name = (void *)&nas_dest_addr;
nas_msg_tx.msg_namelen = sizeof(nas_dest_addr);
nas_msg_tx.msg_iov = &nas_iov_tx;
nas_msg_tx.msg_iovlen = 1;
// RX PART
memset(&nas_msg_rx,0,sizeof(nas_msg_rx));
nas_msg_rx.msg_name = (void *)&nas_src_addr;
nas_msg_rx.msg_namelen = sizeof(nas_src_addr);
nas_msg_rx.msg_iov = &nas_iov_rx;
nas_msg_rx.msg_iovlen = 1;
}
return 1;
}
#else /* UE_NAS_USE_TUN */
int netlink_init(void) int netlink_init(void)
{ {
int ret; int ret;
...@@ -119,3 +235,5 @@ int netlink_init(void) ...@@ -119,3 +235,5 @@ int netlink_init(void)
return(nas_sock_fd); return(nas_sock_fd);
} }
#endif /* UE_NAS_USE_TUN */
...@@ -72,7 +72,11 @@ extern struct nlmsghdr *nas_nlh_tx; ...@@ -72,7 +72,11 @@ extern struct nlmsghdr *nas_nlh_tx;
extern struct nlmsghdr *nas_nlh_rx; extern struct nlmsghdr *nas_nlh_rx;
extern struct iovec nas_iov_tx; extern struct iovec nas_iov_tx;
extern struct iovec nas_iov_rx; extern struct iovec nas_iov_rx;
#ifdef UE_NAS_USE_TUN
extern int nas_sock_fd[NUMBER_OF_UE_MAX];
#else
extern int nas_sock_fd; extern int nas_sock_fd;
#endif
extern struct msghdr nas_msg_tx; extern struct msghdr nas_msg_tx;
extern struct msghdr nas_msg_rx; extern struct msghdr nas_msg_rx;
...@@ -239,7 +243,11 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP) ...@@ -239,7 +243,11 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP)
nas_nlh_tx->nlmsg_len += pdcp_output_sdu_bytes_to_write; nas_nlh_tx->nlmsg_len += pdcp_output_sdu_bytes_to_write;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_SIZE, pdcp_output_sdu_bytes_to_write); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_SIZE, pdcp_output_sdu_bytes_to_write);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 1 );
#ifdef UE_NAS_USE_TUN
ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
#else
ret = sendmsg(nas_sock_fd,&nas_msg_tx,0); ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 0 );
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_ERR, ret ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_ERR, ret );
...@@ -372,6 +380,62 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP) ...@@ -372,6 +380,62 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
{ {
#ifdef UE_NAS_USE_TUN
protocol_ctxt_t ctxt = *ctxt_pP;
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
pdcp_t* pdcp_p = NULL;
int len;
rb_id_t rab_id = DEFAULT_RAB_ID;
do {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 1 );
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER, 1 );
len = read(nas_sock_fd[ctxt_pP->module_id], &nl_rx_buf, NL_MAX_PAYLOAD);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER, 0 );
if (len<=0) continue;
LOG_D(PDCP, "PDCP_COLL_KEY_DEFAULT_DRB_VALUE(module_id=%d, rnti=%x, enb_flag=%d)\n",
ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
if (h_rc == HASH_TABLE_OK) {
LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %d \n",
ctxt.frame, ctxt.instance, len, rab_id);
LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
ctxt.rnti, rab_id);
MSC_LOG_RX_MESSAGE((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
NULL, 0,
MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
MSC_AS_TIME_ARGS(ctxt_pP),
ctxt.instance, rab_id, rab_id, len);
pdcp_data_req(&ctxt, SRB_FLAG_NO, rab_id, RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO, len, nl_rx_buf,
PDCP_TRANSMISSION_MODE_DATA);
} else {
MSC_LOG_RX_DISCARDED_MESSAGE(
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
NULL,
0,
MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
MSC_AS_TIME_ARGS(ctxt_pP),
ctxt.instance, rab_id, rab_id, len);
LOG_D(PDCP,
"[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
ctxt.rnti, rab_id, key);
}
} while (len > 0);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 0 );
return len;
#else /* UE_NAS_USE_TUN */
#ifdef PDCP_USE_NETLINK #ifdef PDCP_USE_NETLINK
protocol_ctxt_t ctxt_cpy = *ctxt_pP; protocol_ctxt_t ctxt_cpy = *ctxt_pP;
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt;
...@@ -764,6 +828,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP) ...@@ -764,6 +828,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
#else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO #else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO
return 0; return 0;
#endif // PDCP_USE_NETLINK #endif // PDCP_USE_NETLINK
#endif /* #else UE_NAS_USE_TUN */
} }
......
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