f1ap_cu_task.c 8.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

22
/*! \file openair2/F1AP/f1ap_cu_task.c
23 24 25 26 27 28 29 30 31 32 33 34
* \brief data structures for F1 interface modules
* \author EURECOM/NTUST
* \date 2018
* \version 0.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr, bing-kai.hong@eurecom.fr
* \note
* \warning
*/

#include "f1ap_common.h"
#include "f1ap_cu_interface_management.h"
35
#include "f1ap_cu_rrc_message_transfer.h"
36
#include "f1ap_cu_ue_context_management.h"
37
#include "f1ap_cu_paging.h"
38
#include "f1ap_cu_task.h"
39
#include <openair3/ocp-gtpu/gtp_itf.h>
40

Laurent THOMAS's avatar
Laurent THOMAS committed
41 42 43
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
instance_t CUuniqInstance=0;

44
static instance_t cu_task_create_gtpu_instance(eth_params_t *IPaddrs) {
Laurent Thomas's avatar
Laurent Thomas committed
45
  openAddr_t tmp= {0};
Laurent Thomas's avatar
Laurent Thomas committed
46
  strncpy(tmp.originHost, IPaddrs->my_addr, sizeof(tmp.originHost)-1);
47
  sprintf(tmp.originService, "%d", IPaddrs->my_portd);
Laurent THOMAS's avatar
Laurent THOMAS committed
48
  return gtpv1Init(tmp);
Laurent Thomas's avatar
Laurent Thomas committed
49 50
}

51 52
static void cu_task_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind)
{
53
  createF1inst(true, instance, NULL);
54

55
  // save the assoc id
56 57 58
  f1ap_setup_req_t *f1ap_cu_data = f1ap_req(true, instance);
  f1ap_cu_data->assoc_id = sctp_new_association_ind->assoc_id;
  f1ap_cu_data->sctp_in_streams = sctp_new_association_ind->in_streams;
59 60
  f1ap_cu_data->sctp_out_streams = sctp_new_association_ind->out_streams;
  f1ap_cu_data->default_sctp_stream_id = 0;
61 62
}

63
static void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
64 65 66
  DevAssert(sctp_new_association_resp != NULL);

  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
67
    LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
68 69 70
          sctp_new_association_resp->sctp_state,
          instance,
          sctp_new_association_resp->ulp_cnx_id);
71 72
    //if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN)
    //proto_agent_stop(instance);
73 74
    //f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
    return; // exit -1 for debugging
75 76 77
  }
}

78
static void cu_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
79 80
  int result;
  DevAssert(sctp_data_ind != NULL);
81
  f1ap_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
82
                      sctp_data_ind->buffer, sctp_data_ind->buffer_length);
83 84 85 86
  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}

Laurent Thomas's avatar
Laurent Thomas committed
87
static void cu_task_send_sctp_init_req(instance_t instance, char *my_addr) {
laurent's avatar
laurent committed
88 89
  // 1. get the itti msg, and retrive the nb_id from the message
  // 2. use RC.rrc[nb_id] to fill the sctp_init_t with the ip, port
90
  // 3. creat an itti message to init
91
  LOG_I(F1AP, "F1AP_CU_SCTP_REQ(create socket)\n");
92
  MessageDef  *message_p = NULL;
93
  message_p = itti_alloc_new_message (TASK_CU_F1, 0, SCTP_INIT_MSG);
94 95 96 97 98
  message_p->ittiMsg.sctp_init.port = F1AP_PORT_NUMBER;
  message_p->ittiMsg.sctp_init.ppid = F1AP_SCTP_PPID;
  message_p->ittiMsg.sctp_init.ipv4 = 1;
  message_p->ittiMsg.sctp_init.ipv6 = 0;
  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
99
  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(my_addr);
100 101 102 103 104 105
  /*
   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
   * * * * Disable it for now.
   */
  message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0;
  message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1";
106
  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
107 108
}

109 110 111 112 113 114 115
void create_gtpInst(instance_t instance, eth_params_t *IPaddrs)
{
  getCxt(CUtype, instance)->gtpInst = cu_task_create_gtpu_instance(IPaddrs);
  AssertFatal(getCxt(CUtype, instance)->gtpInst > 0, "Failed to create CU F1-U UDP listener");
  CUuniqInstance = getCxt(CUtype, instance)->gtpInst;
}

Laurent Thomas's avatar
Laurent Thomas committed
116
void *F1AP_CU_task(void *arg) {
117 118
  MessageDef *received_msg = NULL;
  int         result;
119
  LOG_I(F1AP, "Starting F1AP at CU\n");
120 121
  // no RLC in CU, initialize mem pool for PDCP
  pool_buffer_init();
122
  itti_mark_task_ready(TASK_CU_F1);
Laurent Thomas's avatar
Laurent Thomas committed
123

124 125 126 127 128
  eth_params_t *IPaddrs[RC.nb_nr_inst];
  for (int mod_id = 0; mod_id < RC.nb_nr_inst; mod_id++) {
    IPaddrs[mod_id] = &RC.nrrrc[mod_id]->eth_params_s;
    cu_task_send_sctp_init_req(mod_id, IPaddrs[mod_id]->my_addr);
  }
Laurent Thomas's avatar
Laurent Thomas committed
129

130 131
  while (1) {
    itti_receive_msg(TASK_CU_F1, &received_msg);
132
    LOG_D(F1AP, "CU Task Received %s for instance %ld\n",
133
          ITTI_MSG_NAME(received_msg), ITTI_MSG_DESTINATION_INSTANCE(received_msg));
134
    switch (ITTI_MSG_ID(received_msg)) {
135
      case SCTP_NEW_ASSOCIATION_IND:
136
        cu_task_handle_sctp_association_ind(ITTI_MSG_ORIGIN_INSTANCE(received_msg),
137
                                            &received_msg->ittiMsg.sctp_new_association_ind);
138 139 140
        break;

      case SCTP_NEW_ASSOCIATION_RESP:
141
        cu_task_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
142
                                             &received_msg->ittiMsg.sctp_new_association_resp);
143 144 145
        break;

      case SCTP_DATA_IND:
146
        cu_task_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
147
                                     &received_msg->ittiMsg.sctp_data_ind);
148 149 150
        break;

      case F1AP_SETUP_RESP: // from rrc
151
        CU_send_F1_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
152
                                  &F1AP_SETUP_RESP(received_msg));
153 154
        break;

155 156
      case F1AP_GNB_CU_CONFIGURATION_UPDATE: // from rrc
        CU_send_gNB_CU_CONFIGURATION_UPDATE(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
157
                                            &F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg));
158 159
        break;

160
      case F1AP_DL_RRC_MESSAGE: // from rrc
161
        CU_send_DL_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
162
                                        &F1AP_DL_RRC_MESSAGE(received_msg));
163
        free(F1AP_DL_RRC_MESSAGE(received_msg).rrc_container);
164
        break;
165

166
      case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc
167
        CU_send_UE_CONTEXT_SETUP_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
168
                                         &F1AP_UE_CONTEXT_SETUP_REQ(received_msg));
169 170
        break;

171 172
      case F1AP_UE_CONTEXT_MODIFICATION_REQ:
        CU_send_UE_CONTEXT_MODIFICATION_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
173
                                                &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg));
174 175
        break;

176
      case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc
177
        CU_send_UE_CONTEXT_RELEASE_COMMAND(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
178 179 180
                                           &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg));
        break;

181 182 183 184 185
      case F1AP_PAGING_IND:
        CU_send_Paging(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
                       &F1AP_PAGING_IND(received_msg));
        break;

186 187 188 189 190 191 192
      //    case F1AP_SETUP_RESPONSE: // This is from RRC
      //    CU_send_F1_SETUP_RESPONSE(instance, *f1ap_setup_ind, &(F1AP_SETUP_RESP) f1ap_setup_resp)
      //        break;

      //    case F1AP_SETUP_FAILURE: // This is from RRC
      //    CU_send_F1_SETUP_FAILURE(instance, *f1ap_setup_ind, &(F1AP_SETUP_FAILURE) f1ap_setup_failure)
      //       break;
193 194

      case TERMINATE_MESSAGE:
195
        LOG_W(F1AP, " *** Exiting F1AP thread\n");
196 197 198 199
        itti_exit_task();
        break;

      default:
200 201
        LOG_E(F1AP, "CU Received unhandled message: %d:%s\n",
              ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
202 203
        break;
    } // switch
204

205 206 207 208 209 210
    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    received_msg = NULL;
  } // while

  return NULL;
211
}