Add rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ
Add rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP Fix some problems about pdu session setup
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include "NwGtpv1uPrivate.h"
|
||||
#include "NwLog.h"
|
||||
#include "gtpv1u_eNB_defs.h"
|
||||
#include "gtpv1u_gNB_defs.h"
|
||||
#include "gtpv1_u_messages_types.h"
|
||||
#include "udp_eNB_task.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
@@ -45,7 +46,6 @@
|
||||
#include "COMMON/platform_constants.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "gtpv1u_eNB_defs.h"
|
||||
#include "gtpv1u_eNB_task.h"
|
||||
#include "gtpv1u_gNB_task.h"
|
||||
#include "rrc_eNB_GTPV1U.h"
|
||||
@@ -309,3 +309,343 @@ void *gtpv1u_gNB_task(void *args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nr_gtpv1u_gNB_init(void) {
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uUlpEntityT ulp;
|
||||
NwGtpv1uUdpEntityT udp;
|
||||
NwGtpv1uLogMgrEntityT log;
|
||||
NwGtpv1uTimerMgrEntityT tmr;
|
||||
// enb_properties_p = enb_config_get()->properties[0];
|
||||
RC.nr_gtpv1u_data_g = (nr_gtpv1u_data_t *)calloc(sizeof(nr_gtpv1u_data_t),1);
|
||||
LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.nr_gtpv1u_data_g);
|
||||
|
||||
/* Initialize UE hashtable */
|
||||
RC.nr_gtpv1u_data_g->ue_mapping = hashtable_create (32, NULL, NULL);
|
||||
AssertFatal(RC.nr_gtpv1u_data_g->ue_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create returned %p\n", RC.gtpv1u_data_g->ue_mapping);
|
||||
RC.nr_gtpv1u_data_g->teid_mapping = hashtable_create (256, NULL, NULL);
|
||||
AssertFatal(RC.nr_gtpv1u_data_g->teid_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create\n");
|
||||
// RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up = enb_properties_p->enb_ipv4_address_for_S1U;
|
||||
//gtpv1u_data_g.udp_data;
|
||||
RC.nr_gtpv1u_data_g->seq_num = 0;
|
||||
RC.nr_gtpv1u_data_g->restart_counter = 0;
|
||||
|
||||
/* Initializing GTPv1-U stack */
|
||||
if ((rc = nwGtpv1uInitialize(&RC.nr_gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((rc = nwGtpv1uSetLogLevel(RC.nr_gtpv1u_data_g->gtpv1u_stack,
|
||||
NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "Failed to setup loglevel for stack %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the ULP API callback. Called once message have been processed by the
|
||||
* nw-gtpv1u stack.
|
||||
*/
|
||||
ulp.ulpReqCallback = gtpv1u_gNB_process_stack_req;
|
||||
memset((void *)&(ulp.hUlp), 0, sizeof(NwGtpv1uUlpHandleT));
|
||||
|
||||
if ((rc = nwGtpv1uSetUlpEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* nw-gtpv1u stack requires an udp callback to send data over UDP.
|
||||
* We provide a wrapper to UDP task.
|
||||
*/
|
||||
udp.udpDataReqCallback = gtpv1u_eNB_send_udp_msg;
|
||||
memset((void *)&(udp.hUdp), 0, sizeof(NwGtpv1uUdpHandleT));
|
||||
|
||||
if ((rc = nwGtpv1uSetUdpEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log.logReqCallback = gtpv1u_eNB_log_request;
|
||||
memset((void *)&(log.logMgrHandle), 0, sizeof(NwGtpv1uLogMgrHandleT));
|
||||
|
||||
if ((rc = nwGtpv1uSetLogMgrEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Timer interface is more complicated as both wrappers doesn't send a message
|
||||
* to the timer task but call the timer API functions start/stop timer.
|
||||
*/
|
||||
tmr.tmrMgrHandle = 0;
|
||||
tmr.tmrStartCallback = gtpv1u_start_timer_wrapper;
|
||||
tmr.tmrStopCallback = gtpv1u_stop_timer_wrapper;
|
||||
|
||||
if ((rc = nwGtpv1uSetTimerMgrEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
|
||||
|
||||
if ((ret = gtpv1u_eNB_create_dump_socket()) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
gtpv1u_create_ngu_tunnel(
|
||||
const instance_t instanceP,
|
||||
const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP,
|
||||
gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP)
|
||||
{
|
||||
/* Create a new nw-gtpv1-u stack req using API */
|
||||
NwGtpv1uUlpApiT stack_req;
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
/* Local tunnel end-point identifier */
|
||||
teid_t ngu_teid = 0;
|
||||
nr_gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL;
|
||||
nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL;
|
||||
//MessageDef *message_p = NULL;
|
||||
hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS;
|
||||
int i;
|
||||
pdusessionid_t pdusession_id = 0;
|
||||
// int ipv4_addr = 0;
|
||||
int ip_offset = 0;
|
||||
in_addr_t in_addr;
|
||||
int addrs_length_in_bytes= 0;
|
||||
int loop_counter = 0;
|
||||
int ret = 0;
|
||||
MSC_LOG_RX_MESSAGE(
|
||||
MSC_GTPU_GNB,
|
||||
MSC_RRC_GNB,
|
||||
NULL,0,
|
||||
MSC_AS_TIME_FMT" CREATE_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u psid %u upf-ngu teid %u",
|
||||
0,0,create_tunnel_req_pP->rnti, instanceP,
|
||||
create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->pdusession_id[0],
|
||||
create_tunnel_req_pP->upf_NGu_teid[0]);
|
||||
create_tunnel_resp_pP->rnti = create_tunnel_req_pP->rnti;
|
||||
create_tunnel_resp_pP->status = 0;
|
||||
create_tunnel_resp_pP->num_tunnels = 0;
|
||||
|
||||
for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
|
||||
ip_offset = 0;
|
||||
loop_counter = 0;
|
||||
pdusession_id = create_tunnel_req_pP->pdusession_id[i];
|
||||
LOG_D(GTPU, "Rx GTPV1U_GNB_CREATE_TUNNEL_REQ ue rnti %x pdu session id %u\n",
|
||||
create_tunnel_req_pP->rnti, pdusession_id);
|
||||
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
|
||||
stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
|
||||
|
||||
do {
|
||||
ngu_teid = gtpv1u_new_teid();
|
||||
LOG_D(GTPU, "gtpv1u_create_ngu_tunnel() 0x%x %u(dec)\n", ngu_teid, ngu_teid);
|
||||
stack_req.apiInfo.createTunnelEndPointInfo.teid = ngu_teid;
|
||||
stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0;
|
||||
stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
|
||||
rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req);
|
||||
LOG_D(GTPU, ".\n");
|
||||
loop_counter++;
|
||||
} while (rc != NW_GTPV1U_OK && loop_counter < 10);
|
||||
|
||||
if ( rc != NW_GTPV1U_OK && loop_counter == 10 ) {
|
||||
LOG_E(GTPU,"NwGtpv1uCreateTunnelEndPoint failed 10 times,start next loop\n");
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
//-----------------------
|
||||
// PDCP->GTPV1U mapping
|
||||
//-----------------------
|
||||
hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)>pv1u_ue_data_p);
|
||||
|
||||
if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_OK)) {
|
||||
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
|
||||
gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t));
|
||||
hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
|
||||
AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
|
||||
}
|
||||
|
||||
gtpv1u_ue_data_p->ue_id = create_tunnel_req_pP->rnti;
|
||||
gtpv1u_ue_data_p->instance_id = 0; // TO DO
|
||||
memcpy(&create_tunnel_resp_pP->gnb_addr.buffer,
|
||||
&RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up,
|
||||
sizeof (in_addr_t));
|
||||
|
||||
LOG_I(GTPU,"Configured GTPu address : %x\n",RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up);
|
||||
create_tunnel_resp_pP->gnb_addr.length = sizeof (in_addr_t);
|
||||
addrs_length_in_bytes = create_tunnel_req_pP->upf_addr[i].length / 8;
|
||||
AssertFatal((addrs_length_in_bytes == 4) ||
|
||||
(addrs_length_in_bytes == 16) ||
|
||||
(addrs_length_in_bytes == 20),
|
||||
"Bad transport layer address length %d (bits) %d (bytes)",
|
||||
create_tunnel_req_pP->upf_addr[i].length, addrs_length_in_bytes);
|
||||
|
||||
if ((addrs_length_in_bytes == 4) ||
|
||||
(addrs_length_in_bytes == 20)) {
|
||||
in_addr = *((in_addr_t *)create_tunnel_req_pP->upf_addr[i].buffer);
|
||||
ip_offset = 4;
|
||||
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip_addr = in_addr;
|
||||
}
|
||||
|
||||
if ((addrs_length_in_bytes == 16) ||
|
||||
(addrs_length_in_bytes == 20)) {
|
||||
memcpy(gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip6_addr.s6_addr,
|
||||
&create_tunnel_req_pP->upf_addr[i].buffer[ip_offset],
|
||||
16);
|
||||
}
|
||||
|
||||
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].state = BEARER_IN_CONFIG;
|
||||
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB = ngu_teid;
|
||||
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB_stack_session = stack_req.apiInfo.createTunnelEndPointInfo.hStackSession;
|
||||
gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_upf = create_tunnel_req_pP->upf_NGu_teid[i];
|
||||
gtpv1u_ue_data_p->num_bearers++;
|
||||
create_tunnel_resp_pP->gnb_NGu_teid[i] = ngu_teid;
|
||||
|
||||
LOG_I(GTPU,"Copied to create_tunnel_resp tunnel: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n",
|
||||
i,
|
||||
create_tunnel_resp_pP->gnb_addr.buffer[0],
|
||||
create_tunnel_resp_pP->gnb_addr.buffer[1],
|
||||
create_tunnel_resp_pP->gnb_addr.buffer[2],
|
||||
create_tunnel_resp_pP->gnb_addr.buffer[3],
|
||||
create_tunnel_resp_pP->gnb_addr.length,
|
||||
create_tunnel_resp_pP->gnb_NGu_teid[i]);
|
||||
} else {
|
||||
create_tunnel_resp_pP->gnb_NGu_teid[i] = 0;
|
||||
create_tunnel_resp_pP->status = 0xFF;
|
||||
}
|
||||
|
||||
create_tunnel_resp_pP->pdusession_id[i] = pdusession_id;
|
||||
create_tunnel_resp_pP->num_tunnels += 1;
|
||||
//-----------------------
|
||||
// GTPV1U->PDCP mapping
|
||||
//-----------------------
|
||||
hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, (void **)>pv1u_teid_data_p);
|
||||
|
||||
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
|
||||
gtpv1u_teid_data_p = calloc (1, sizeof(nr_gtpv1u_teid_data_t));
|
||||
gtpv1u_teid_data_p->gnb_id = 0; // TO DO
|
||||
gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti;
|
||||
gtpv1u_teid_data_p->pdu_session_id = pdusession_id;
|
||||
hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, gtpv1u_teid_data_p);
|
||||
AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
|
||||
} else {
|
||||
create_tunnel_resp_pP->gnb_NGu_teid[i] = 0;
|
||||
create_tunnel_resp_pP->status = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
MSC_LOG_TX_MESSAGE(
|
||||
MSC_GTPU_GNB,
|
||||
MSC_RRC_GNB,
|
||||
NULL,0,
|
||||
"0 GTPV1U_GNB_CREATE_TUNNEL_RESP rnti %x teid %x",
|
||||
create_tunnel_resp_pP->rnti,
|
||||
ngu_teid);
|
||||
LOG_D(GTPU, "Tx GTPV1U_GNB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
|
||||
create_tunnel_req_pP->rnti,
|
||||
create_tunnel_resp_pP->status);
|
||||
//return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static int gtpv1u_gNB_send_init_udp(const Gtpv1uNGReq *req) {
|
||||
// Create and alloc new message
|
||||
MessageDef *message_p;
|
||||
struct in_addr addr= {0};
|
||||
message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT);
|
||||
|
||||
if (message_p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
UDP_INIT(message_p).port = req->gnb_port_for_NGu_up;
|
||||
addr.s_addr = req->gnb_ip_address_for_NGu_up;
|
||||
UDP_INIT(message_p).address = inet_ntoa(addr);
|
||||
LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,UDP_INIT(message_p).port);
|
||||
MSC_LOG_EVENT(
|
||||
MSC_GTPU_ENB,
|
||||
"0 UDP bind %s:%u",
|
||||
UDP_INIT(message_p).address,
|
||||
UDP_INIT(message_p).port);
|
||||
return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
static int gtpv1u_ng_req(
|
||||
const instance_t instanceP,
|
||||
const Gtpv1uNGReq *const req) {
|
||||
memcpy(&RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up,
|
||||
&req->gnb_ip_address_for_NGu_up,
|
||||
sizeof (req->gnb_ip_address_for_NGu_up));
|
||||
gtpv1u_gNB_send_init_udp(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void *gtpv1u_gNB_process_itti_msg(void *notUsed) {
|
||||
/* 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.
|
||||
*/
|
||||
instance_t instance;
|
||||
MessageDef *received_message_p = NULL;
|
||||
int rc = 0;
|
||||
itti_receive_msg(TASK_GTPV1_U, &received_message_p);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
|
||||
DevAssert(received_message_p != NULL);
|
||||
instance = ITTI_MSG_INSTANCE(received_message_p);
|
||||
|
||||
switch (ITTI_MSG_ID(received_message_p)) {
|
||||
case GTPV1U_GNB_NG_REQ:
|
||||
gtpv1u_ng_req(instance, &received_message_p->ittiMsg.gtpv1uNGReq);
|
||||
break;
|
||||
|
||||
case TERMINATE_MESSAGE: {
|
||||
if (RC.nr_gtpv1u_data_g->ue_mapping != NULL) {
|
||||
hashtable_destroy (&(RC.nr_gtpv1u_data_g->ue_mapping));
|
||||
}
|
||||
|
||||
if (RC.nr_gtpv1u_data_g->teid_mapping != NULL) {
|
||||
hashtable_destroy (&(RC.nr_gtpv1u_data_g->teid_mapping));
|
||||
}
|
||||
|
||||
LOG_W(GTPU, " *** Exiting GTPU thread\n");
|
||||
itti_exit_task();
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_HAS_EXPIRED:
|
||||
nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg);
|
||||
break;
|
||||
|
||||
default: {
|
||||
LOG_E(GTPU, "Unkwnon message ID %d:%s\n",
|
||||
ITTI_MSG_ID(received_message_p),
|
||||
ITTI_MSG_NAME(received_message_p));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rc = itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
|
||||
AssertFatal(rc == EXIT_SUCCESS, "Failed to free memory (%d)!\n", rc);
|
||||
received_message_p = NULL;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *nr_gtpv1u_gNB_task(void *args) {
|
||||
int rc = 0;
|
||||
rc = nr_gtpv1u_gNB_init();
|
||||
AssertFatal(rc == 0, "gtpv1u_gNB_init Failed");
|
||||
itti_mark_task_ready(TASK_GTPV1_U);
|
||||
MSC_START_USE();
|
||||
|
||||
while(1) {
|
||||
(void) gtpv1u_gNB_process_itti_msg (NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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 rrc_gNB_NGAP.h
|
||||
* \brief rrc NGAP procedures for gNB
|
||||
* \author Yoshio INOUE, Masayuki HARADA
|
||||
* \date 2020
|
||||
* \version 0.1
|
||||
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com
|
||||
* (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
|
||||
*/
|
||||
|
||||
#include "hashtable.h"
|
||||
#include "NR_asn_constant.h"
|
||||
|
||||
#ifndef GTPV1U_GNB_DEFS_H_
|
||||
#define GTPV1U_GNB_DEFS_H_
|
||||
|
||||
#include "NwGtpv1u.h"
|
||||
|
||||
#define GTPV1U_UDP_PORT (2152)
|
||||
|
||||
#define NR_GTPV1U_MAX_BEARERS_ID (max_val_NR_DRB_Identity - 3)
|
||||
|
||||
#define GTPV1U_SOURCE_GNB (0)
|
||||
#define GTPV1U_TARGET_GNB (1)
|
||||
#define GTPV1U_MSG_FROM_SOURCE_GNB (0)
|
||||
#define GTPV1U_MSG_FROM_UPF (1)
|
||||
|
||||
|
||||
typedef struct nr_gtpv1u_teid_data_s {
|
||||
/* UE identifier for oaisim stack */
|
||||
module_id_t gnb_id;
|
||||
rnti_t ue_id;
|
||||
pdusessionid_t pdu_session_id;
|
||||
} nr_gtpv1u_teid_data_t;
|
||||
|
||||
|
||||
typedef struct nr_gtpv1u_bearer_s {
|
||||
/* TEID used in dl and ul */
|
||||
teid_t teid_gNB; ///< gNB TEID
|
||||
uintptr_t teid_gNB_stack_session; ///< gNB TEID
|
||||
teid_t teid_upf; ///< Remote TEID
|
||||
in_addr_t upf_ip_addr;
|
||||
struct in6_addr upf_ip6_addr;
|
||||
teid_t teid_tgNB;
|
||||
in_addr_t tgnb_ip_addr; ///< target gNB ipv4
|
||||
struct in6_addr tgnb_ip6_addr; ///< target gNB ipv6
|
||||
tcp_udp_port_t port;
|
||||
//NwGtpv1uStackSessionHandleT stack_session;
|
||||
bearer_state_t state;
|
||||
} nr_gtpv1u_bearer_t;
|
||||
|
||||
typedef struct nr_gtpv1u_ue_data_s {
|
||||
/* UE identifier for oaisim stack */
|
||||
rnti_t ue_id;
|
||||
|
||||
/* Unique identifier used between PDCP and GTP-U to distinguish UEs */
|
||||
uint32_t instance_id;
|
||||
int num_bearers;
|
||||
/* Bearer related data.
|
||||
* Note that the first LCID available for data is 3 and we fixed the maximum
|
||||
* number of e-rab per UE to be (32 [id range]), max RB is 11. The real rb id will 3 + rab_id (3..32).
|
||||
*/
|
||||
nr_gtpv1u_bearer_t bearers[NR_GTPV1U_MAX_BEARERS_ID];
|
||||
|
||||
//RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node;
|
||||
} nr_gtpv1u_ue_data_t;
|
||||
|
||||
typedef struct nr_gtpv1u_data_s {
|
||||
/* nwgtpv1u stack internal data */
|
||||
NwGtpv1uStackHandleT gtpv1u_stack;
|
||||
|
||||
/* RB tree of UEs */
|
||||
hash_table_t *ue_mapping; // PDCP->GTPV1U
|
||||
hash_table_t *teid_mapping; // GTPV1U -> PDCP
|
||||
|
||||
//RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head;
|
||||
/* Local IP address to use */
|
||||
in_addr_t gnb_ip_address_for_NGu_up;
|
||||
/* UDP internal data */
|
||||
//udp_data_t udp_data;
|
||||
|
||||
uint16_t seq_num;
|
||||
uint8_t restart_counter;
|
||||
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
char *interface_name;
|
||||
int interface_index;
|
||||
|
||||
struct iovec *malloc_ring;
|
||||
void *sock_mmap_ring[16];
|
||||
int sock_desc[16]; // indexed by marking
|
||||
#endif
|
||||
} nr_gtpv1u_data_t;
|
||||
|
||||
|
||||
#endif /* GTPV1U_GNB_DEFS_H_ */
|
||||
@@ -32,6 +32,13 @@ int gtpv1u_gNB_init(void);
|
||||
|
||||
void *gtpv1u_gNB_task(void *args);
|
||||
|
||||
void *nr_gtpv1u_gNB_task(void *args);
|
||||
|
||||
int
|
||||
gtpv1u_create_ngu_tunnel(
|
||||
const instance_t instanceP,
|
||||
const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP,
|
||||
gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP);
|
||||
|
||||
#endif /* GTPV1U_GNB_TASK_H_ */
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
//ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "msc.h"
|
||||
#include "NGAP_NonDynamic5QIDescriptor.h"
|
||||
|
||||
static
|
||||
int ngap_gNB_handle_ng_setup_response(uint32_t assoc_id,
|
||||
@@ -955,7 +956,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id,
|
||||
}
|
||||
|
||||
|
||||
dec_rval = uper_decode(NULL,
|
||||
dec_rval = aper_decode(NULL,
|
||||
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
|
||||
(void **)&pdusessionTransfer_p,
|
||||
item_p->pDUSessionResourceSetupRequestTransfer.buf,
|
||||
@@ -1028,7 +1029,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id,
|
||||
qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx];
|
||||
|
||||
/* Set the QOS informations */
|
||||
NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qci = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
|
||||
NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
|
||||
|
||||
NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level =
|
||||
qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;
|
||||
@@ -1289,11 +1290,11 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id,
|
||||
}
|
||||
|
||||
/* Initial context request = UE-related procedure -> stream != 0 */
|
||||
if (stream == 0) {
|
||||
NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
|
||||
assoc_id, stream);
|
||||
return -1;
|
||||
}
|
||||
// if (stream == 0) {
|
||||
// NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n",
|
||||
// assoc_id, stream);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
ue_desc_p->rx_stream = stream;
|
||||
|
||||
@@ -1338,7 +1339,7 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id,
|
||||
NGAP_WARN("NAS PDU is not provided, generate a PDUSESSION_SETUP Failure (TBD) back to AMF \n");
|
||||
}
|
||||
|
||||
dec_rval = uper_decode(NULL,
|
||||
dec_rval = aper_decode(NULL,
|
||||
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
|
||||
(void **)&pdusessionTransfer_p,
|
||||
item_p->pDUSessionResourceSetupRequestTransfer.buf,
|
||||
@@ -1407,8 +1408,13 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id,
|
||||
qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx];
|
||||
|
||||
/* Set the QOS informations */
|
||||
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qci = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
|
||||
|
||||
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
|
||||
if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){
|
||||
if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){
|
||||
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI =
|
||||
(uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI;
|
||||
}
|
||||
}
|
||||
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
|
||||
qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;
|
||||
NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability =
|
||||
@@ -1668,7 +1674,7 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id,
|
||||
continue;
|
||||
}
|
||||
|
||||
dec_rval = uper_decode(NULL,
|
||||
dec_rval = aper_decode(NULL,
|
||||
&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
|
||||
(void **)&pdusessionTransfer_p,
|
||||
item_p->pDUSessionResourceModifyRequestTransfer.buf,
|
||||
@@ -1709,7 +1715,7 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id,
|
||||
qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[qosIdx];
|
||||
|
||||
/* Set the QOS informations */
|
||||
NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qci = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
|
||||
NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
|
||||
if(qosFlowItem_p->qosFlowLevelQosParameters) {
|
||||
NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
|
||||
qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP;
|
||||
|
||||
@@ -750,7 +750,7 @@ int ngap_gNB_initial_ctxt_resp(
|
||||
ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t));
|
||||
|
||||
/* qosFlowIdentifier */
|
||||
ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qci;
|
||||
ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qfi;
|
||||
|
||||
/* qosFlowMappingIndication */
|
||||
if(initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
|
||||
@@ -1039,6 +1039,8 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance,
|
||||
pdusessionTransfer_p = (NGAP_PDUSessionResourceSetupResponseTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseTransfer_t));
|
||||
|
||||
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel;
|
||||
pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel =
|
||||
calloc(1, sizeof(struct NGAP_GTPTunnel));
|
||||
|
||||
GTP_TEID_TO_ASN1(pdusession_setup_resp_p->pdusessions[i].gtp_teid, &pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID);
|
||||
|
||||
@@ -1064,7 +1066,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance,
|
||||
ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t));
|
||||
|
||||
/* qosFlowIdentifier */
|
||||
ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qci;
|
||||
ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qfi;
|
||||
|
||||
/* qosFlowMappingIndication */
|
||||
if(pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) {
|
||||
@@ -1075,11 +1077,19 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance,
|
||||
}
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
|
||||
item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
|
||||
item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
|
||||
// res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
|
||||
// item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer;
|
||||
// item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded;
|
||||
char buffer[100];
|
||||
asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer,
|
||||
NULL,
|
||||
pdusessionTransfer_p,
|
||||
buffer,100);
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
|
||||
item->pDUSessionResourceSetupResponseTransfer.buf = buffer;
|
||||
item->pDUSessionResourceSetupResponseTransfer.size = enc_rval.encoded;
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
|
||||
//ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p);
|
||||
|
||||
ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceSetupListSURes.list, item);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user