Files
openairinterface5g/openair-cn/SGI/sgi_task.c
T

332 lines
13 KiB
C

/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file sgi_task.c
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <net/if.h>
//-----------------------------------------------------------------------------
#include "assertions.h"
#include "mme_config.h"
#include "intertask_interface.h"
#include "sgi.h"
//-----------------------------------------------------------------------------
static void* sgi_task_thread(void *args_p);
static int sgi_create_endpoint_request(sgi_data_t *sgi_dataP, SGICreateEndpointReq *req_p);
static int sgi_update_endpoint_request(sgi_data_t *sgi_dataP, SGIUpdateEndpointReq *req_p);
static int sgi_init_phase2(sgi_data_t *sgi_data_pP);
//-----------------------------------------------------------------------------
static pthread_t fw_2_sgi_task_thread;
//-----------------------------------------------------------------------------
static void* sgi_task_thread(void *args_p)
//-----------------------------------------------------------------------------
{
sgi_data_t *sgi_data_p;
if (args_p == NULL) {
return NULL;
}
itti_mark_task_ready(TASK_FW_IP);
sgi_data_p = (sgi_data_t *)args_p;
while(1) {
/* Trying to fetch a message from the message queue.
* If the queue is empty, this function will block till a
* message is sent to the task.
*/
MessageDef *received_message_p;
itti_receive_msg(TASK_FW_IP, &received_message_p);
DevAssert(received_message_p != NULL);
if (sgi_data_p->hss_associated) {
switch (ITTI_MSG_ID(received_message_p))
{
case GTPV1U_TUNNEL_DATA_IND: {
/* We received data from GTPV1_U incoming from an UE.
* Forward it host adapter.
*/
Gtpv1uTunnelDataInd *data_ind_p;
data_ind_p = &received_message_p->ittiMsg.gtpv1uTunnelDataInd;
sgi_send_data(&data_ind_p->buffer[data_ind_p->offset], data_ind_p->length, sgi_data_p, data_ind_p->local_S1u_teid);
/* Buffer is no longer needed, free it */
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_ind_p->buffer);
}
break;
case SGI_CREATE_ENDPOINT_REQUEST: {
SGICreateEndpointReq *req_p;
req_p = &received_message_p->ittiMsg.sgiCreateEndpointReq;
sgi_create_endpoint_request(sgi_data_p, req_p);
}
break;
case SGI_UPDATE_ENDPOINT_REQUEST: {
SGIUpdateEndpointReq *req_p;
req_p = &received_message_p->ittiMsg.sgiUpdateEndpointReq;
sgi_update_endpoint_request(sgi_data_p, req_p);
}
break;
default: {
SGI_IF_ERROR("Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
}
break;
}
}else {
switch (ITTI_MSG_ID(received_message_p))
{
case ACTIVATE_MESSAGE: {
sgi_data_p->hss_associated = 1;
SGI_IF_DEBUG("HSS ASSOCIATED, CAN START VLANS (bug in freediameter)");
sgi_init_phase2(sgi_data_p);
} break;
default: {
SGI_IF_ERROR("Unkwnon or ignored message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
}
break;
}
}
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
}
//------------------------------------------------------
static int sgi_create_endpoint_request(sgi_data_t *sgi_dataP, SGICreateEndpointReq *req_p)
//------------------------------------------------------
{
SGICreateEndpointResp *sgi_create_endpoint_resp_p;
MessageDef *message_p;
sgi_teid_mapping_t *mapping;
SGI_IF_DEBUG("Rx IP_FW_CREATE_SGI_ENDPOINT_REQUEST, Context: S-GW S11 teid %u, S-GW S1U teid %u EPS bearer id %u\n",
req_p->context_teid, req_p->sgw_S1u_teid, req_p->eps_bearer_id);
message_p = itti_alloc_new_message(TASK_FW_IP, SGI_CREATE_ENDPOINT_RESPONSE);
if (message_p == NULL) {
return -1;
}
sgi_create_endpoint_resp_p = &message_p->ittiMsg.sgiCreateEndpointResp;
sgi_create_endpoint_resp_p->context_teid = req_p->context_teid;
sgi_create_endpoint_resp_p->sgw_S1u_teid = req_p->sgw_S1u_teid;
sgi_create_endpoint_resp_p->eps_bearer_id = req_p->eps_bearer_id;
sgi_create_endpoint_resp_p->pdn_type = req_p->pdn_type;
sgi_create_endpoint_resp_p->paa = req_p->paa;
sgi_create_endpoint_resp_p->status = SGI_STATUS_OK;
if (hashtable_is_key_exists(sgi_dataP->teid_mapping, req_p->sgw_S1u_teid) == HASH_TABLE_OK)
{
SGI_IF_ERROR("SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST Context: S11 teid %u\n", req_p->context_teid);
sgi_create_endpoint_resp_p->status = SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST;
} else {
mapping = malloc(sizeof(sgi_teid_mapping_t));
if (mapping == NULL) {
sgi_create_endpoint_resp_p->status = SGI_STATUS_ERROR_NO_MEMORY_AVAILABLE;
} else {
memset(mapping, 0 , sizeof(sgi_teid_mapping_t));
mapping->eps_bearer_id = req_p->eps_bearer_id;
mapping->enb_S1U_teid = -1;
if (hashtable_insert(sgi_dataP->teid_mapping, req_p->sgw_S1u_teid, mapping) != 0) {
SGI_IF_ERROR("SGI_STATUS_ERROR_SYSTEM_FAILURE Context: S11 teid %u\n", req_p->context_teid);
sgi_create_endpoint_resp_p->status = SGI_STATUS_ERROR_SYSTEM_FAILURE;
free(mapping);
} else {
SGI_IF_ERROR("SGI_STATUS_OK Context: S11 teid %u\n", req_p->context_teid);
sgi_create_endpoint_resp_p->status = SGI_STATUS_OK;
}
}
}
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
}
//------------------------------------------------------
static int sgi_update_endpoint_request(sgi_data_t *sgi_dataP, SGIUpdateEndpointReq *req_p)
//------------------------------------------------------
{
SGIUpdateEndpointResp *sgi_update_endpoint_resp_p = NULL;
MessageDef *message_p = NULL;
sgi_teid_mapping_t *mapping = NULL;
SGI_IF_DEBUG("Rx IP_FW_UPDATE_SGI_ENDPOINT_REQUEST, Context: S-GW S11 teid %u, S-GW S1U teid %u EPS bearer id %u\n",
req_p->context_teid, req_p->sgw_S1u_teid, req_p->eps_bearer_id);
message_p = itti_alloc_new_message(TASK_FW_IP, SGI_UPDATE_ENDPOINT_RESPONSE);
if (message_p == NULL) {
return -1;
}
sgi_update_endpoint_resp_p = &message_p->ittiMsg.sgiUpdateEndpointResp;
sgi_update_endpoint_resp_p->context_teid = req_p->context_teid;
sgi_update_endpoint_resp_p->sgw_S1u_teid = req_p->sgw_S1u_teid;
sgi_update_endpoint_resp_p->eps_bearer_id = req_p->eps_bearer_id;
sgi_update_endpoint_resp_p->enb_S1u_teid = req_p->enb_S1u_teid;
sgi_update_endpoint_resp_p->status = SGI_STATUS_OK;
if (hashtable_get(sgi_dataP->teid_mapping, req_p->sgw_S1u_teid, (void**)&mapping) == HASH_TABLE_OK)
{
mapping->enb_S1U_teid = req_p->enb_S1u_teid;
} else {
SGI_IF_ERROR("SGI_STATUS_ERROR_CONTEXT_NOT_FOUND Context: S11 teid %u\n", req_p->context_teid);
sgi_update_endpoint_resp_p->status = SGI_STATUS_ERROR_CONTEXT_NOT_FOUND;
}
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
}
//-----------------------------------------------------------------------------
int sgi_init(const pgw_config_t *pgw_config_p)
//-----------------------------------------------------------------------------
{
volatile sgi_data_t *sgi_data_p;
int len;
int i;
SGI_IF_DEBUG("Initializing FW_IP task interface\n");
sgi_data_p = malloc(sizeof(sgi_data_t));
memset((void *)sgi_data_p, 0, sizeof(sgi_data_t));
for (i=0; i < SGI_MAX_EPS_BEARERS_PER_USER; i++) {
sgi_data_p->sd[i] = -1;
}
sgi_data_p->thread_started = 0;
pthread_mutex_init (&sgi_data_p->thread_started_mutex, NULL);
sgi_data_p->teid_mapping = hashtable_create (SGI_MAX_EPS_BEARERS, NULL, NULL);
if (sgi_data_p->teid_mapping == NULL) {
SGI_IF_ERROR("Failed to create SGI hashtable teid_mapping\n");
return -1;
}
sgi_data_p->addr_v4_mapping = hashtable_create (SGI_MAX_SERVED_USERS_PER_PGW, NULL, NULL);
if (sgi_data_p->addr_v4_mapping == NULL) {
SGI_IF_ERROR("Failed to create SGI hashtable addr_v4_mapping\n");
return -1;
}
sgi_data_p->addr_v6_mapping = obj_hashtable_create (SGI_MAX_SERVED_USERS_PER_PGW, NULL, NULL, NULL);
if (sgi_data_p->addr_v6_mapping == NULL) {
SGI_IF_ERROR("Failed to create SGI hashtable addr_v6_mapping\n");
return -1;
}
len = strlen(pgw_config_p->ipv4.pgw_interface_name_for_SGI);
sgi_data_p->interface_name = calloc(len + 1, sizeof(char));
memcpy(sgi_data_p->interface_name, pgw_config_p->ipv4.pgw_interface_name_for_SGI, len);
sgi_data_p->interface_name[len] = '\0';
sgi_data_p->ipv4_addr = pgw_config_p->ipv4.pgw_ipv4_address_for_SGI;
if (pthread_create(&fw_2_sgi_task_thread, NULL, &sgi_task_thread, (void *)sgi_data_p) < 0) {
SGI_IF_ERROR("sgi_task_thread pthread_create: %s", strerror(errno));
return -1;
}
return 0;
}
int sgi_init_phase2(sgi_data_t *sgi_data_pP) {
int i;
if (strcmp(sgi_data_pP->interface_name, PGW_CONFIG_STRING_INTERFACE_DISABLED) != 0) {
sgi_data_pP->interface_index = if_nametoindex(sgi_data_pP->interface_name);
if (sgi_create_sockets(sgi_data_pP) < 0) {
SGI_IF_ERROR("Could not create socket, leaving thread %s\n", __FUNCTION__);
free(sgi_data_pP);
return -1;
}
} else {
SGI_IF_WARNING("SGI interface disabled by config file\n");
}
if (strcmp(sgi_data_pP->interface_name, PGW_CONFIG_STRING_INTERFACE_DISABLED) != 0) {
#ifdef ENABLE_USE_PCAP_FOR_SGI
if (pthread_create(&sgi_data_pP->capture_on_sgi_if_thread, NULL, &sgi_pcap_fw_2_gtpv1u_thread, (void *)sgi_data_pP) < 0) {
SGI_IF_ERROR("sgi_pcap_fw_2_gtpv1u_thread pthread_create: %s", strerror(errno));
return -1;
}
#endif
#ifdef ENABLE_USE_NETFILTER_FOR_SGI
if (pthread_create(&sgi_data_pP->capture_on_sgi_if_thread, NULL, &sgi_nf_fw_2_gtpv1u_thread, (void *)sgi_data_pP) < 0) {
SGI_IF_ERROR("sgi_nf_fw_2_gtpv1u_thread pthread_create: %s", strerror(errno));
return -1;
}
#endif
//#if 0
#ifdef ENABLE_USE_RAW_SOCKET_FOR_SGI
for (i=0; i < SGI_MAX_EPS_BEARERS_PER_USER; i++) {
sgi_read_thread_args_t *args_p = malloc(sizeof(sgi_read_thread_args_t));
args_p->sgi_data = sgi_data_pP;
args_p->socket_index = i;
if (pthread_create(&sgi_data_pP->capture_on_sgi_if_thread, NULL, &sgi_sock_raw_fw_2_gtpv1u_thread, (void *)args_p) < 0) {
SGI_IF_ERROR("sgi_sock_raw_fw_2_gtpv1u_thread pthread_create: %s", strerror(errno));
return -1;
}
}
#endif
//#endif
}
while (sgi_data_pP->thread_started != SGI_MAX_EPS_BEARERS_PER_USER ) {
usleep(1000);
}
/*SGI_IF_DEBUG("ARP RESOLVING ROUTER...\n");
while (sgi_data_p->hw_address_of_router_captured == 0) {
sgi_send_arp_request(sgi_data_p, "router.eur");
sleep(2);
}*/
SGI_IF_DEBUG("Initializing FW_IP task interface: DONE\n");
return 0;
}