f1ap_du_task.c 9.09 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_du_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_du_interface_management.h"
Robert Schmidt's avatar
Robert Schmidt committed
35
#include "f1ap_du_ue_context_management.h"
36
#include "f1ap_du_rrc_message_transfer.h"
37
#include "f1ap_du_task.h"
38 39
#include "proto_agent.h"

40 41 42 43
void du_task_send_sctp_association_req(instance_t instance, f1ap_setup_req_t *f1ap_setup_req) {
  DevAssert(f1ap_setup_req != NULL);
  MessageDef                 *message_p                   = NULL;
  sctp_new_association_req_t *sctp_new_association_req_p  = NULL;
44
  message_p = itti_alloc_new_message(TASK_DU_F1, 0, SCTP_NEW_ASSOCIATION_REQ);
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
  sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
  sctp_new_association_req_p->ulp_cnx_id = instance;
  sctp_new_association_req_p->port = F1AP_PORT_NUMBER;
  sctp_new_association_req_p->ppid = F1AP_SCTP_PPID;
  sctp_new_association_req_p->in_streams  = f1ap_setup_req->sctp_in_streams;
  sctp_new_association_req_p->out_streams = f1ap_setup_req->sctp_out_streams;
  // remote
  memcpy(&sctp_new_association_req_p->remote_address,
         &f1ap_setup_req->CU_f1_ip_address,
         sizeof(f1ap_setup_req->CU_f1_ip_address));
  // local
  memcpy(&sctp_new_association_req_p->local_address,
         &f1ap_setup_req->DU_f1_ip_address,
         sizeof(f1ap_setup_req->DU_f1_ip_address));
  //printf("sib itti message %s\n", f1ap_setup_req_t->sib1[0]);
Bing-Kai Hong's avatar
Bing-Kai Hong committed
60
  //printf("nr_cellid : %llx (%lld)",f1ap_setup_req->nr_cellid[0],f1ap_setup_req->nr_cellid[0]);
61 62 63 64 65 66 67 68
  //du_f1ap_register_to_sctp
  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
}

void du_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
  DevAssert(sctp_new_association_resp != NULL);

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

  // save the assoc id
78
  f1ap_setup_req_t *f1ap_du_data=f1ap_req(false, instance);
79 80 81
  f1ap_du_data->assoc_id         = sctp_new_association_resp->assoc_id;
  f1ap_du_data->sctp_in_streams  = sctp_new_association_resp->in_streams;
  f1ap_du_data->sctp_out_streams = sctp_new_association_resp->out_streams;
82
  f1ap_du_data->default_sctp_stream_id = 0;
83 84
  /* setup parameters for F1U and start the server */
  const cudu_params_t params = {
Xue Song's avatar
Xue Song committed
85 86 87 88
    .local_ipv4_address  = RC.nrmac[instance]->eth_params_n.my_addr,
    .local_port          = RC.nrmac[instance]->eth_params_n.my_portd,
    .remote_ipv4_address = RC.nrmac[instance]->eth_params_n.remote_addr,
    .remote_port         = RC.nrmac[instance]->eth_params_n.remote_portd
89 90
  };
  AssertFatal(proto_agent_start(instance, &params) == 0,
91
              "could not start PROTO_AGENT for F1U on instance %ld!\n", instance);
92 93 94
  DU_send_F1_SETUP_REQUEST(instance);
}

95
void du_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
96 97
  int result;
  DevAssert(sctp_data_ind != NULL);
98
  f1ap_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
99
                      sctp_data_ind->buffer, sctp_data_ind->buffer_length);
100 101 102 103 104 105 106 107 108
  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}


void *F1AP_DU_task(void *arg) {
  //sctp_cu_init();
  MessageDef *received_msg = NULL;
  int         result;
109
  LOG_I(F1AP, "Starting F1AP at DU\n");
110 111 112 113 114 115 116 117 118 119 120 121 122
  //f1ap_eNB_prepare_internal_data();
  itti_mark_task_ready(TASK_DU_F1);

  // SCTP
  while (1) {
    itti_receive_msg(TASK_DU_F1, &received_msg);

    switch (ITTI_MSG_ID(received_msg)) {
      // case TERMINATE_MESSAGE:
      //   //F1AP_WARN(" *** Exiting F1AP DU thread\n");
      //   itti_exit_task();
      //   break;
      case F1AP_SETUP_REQ: // this is not a true F1 message, but rather an ITTI message sent by enb_app
123
        // 1. save the itti msg so that you can use it to sen f1ap_setup_req, fill the f1ap_setup_req message,
124 125
        // 2. store the message in f1ap context, that is also stored in RC
        // 2. send a sctp_association req
126
        createF1inst(false, ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_SETUP_REQ(received_msg));
127
        LOG_I(F1AP, "DU Task Received F1AP_SETUP_REQ\n");
128
        du_task_send_sctp_association_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
129
                                          &F1AP_SETUP_REQ(received_msg));
130
        break;
131

132
      case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE:
133
        DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MSG_ORIGIN_INSTANCE(received_msg),
134 135 136
            &F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(received_msg));
        break;

137
      case F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE:
138 139 140
        DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
            &F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(received_msg));
        break;
141 142 143 144

      case SCTP_NEW_ASSOCIATION_RESP:
        // 1. store the respon
        // 2. send the f1setup_req
145
        LOG_I(F1AP, "DU Task Received SCTP_NEW_ASSOCIATION_RESP\n");
146
        du_task_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
147
                                             &received_msg->ittiMsg.sctp_new_association_resp);
148 149
        break;

150
      case SCTP_DATA_IND:
151
        // ex: any F1 incoming message for DU ends here
152
        LOG_I(F1AP, "DU Task Received SCTP_DATA_IND\n");
153
        du_task_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
154
                                     &received_msg->ittiMsg.sctp_data_ind);
155 156
        break;

157
      case F1AP_INITIAL_UL_RRC_MESSAGE: // from rrc
158 159 160 161
        LOG_I(F1AP, "DU Task Received F1AP_INITIAL_UL_RRC_MESSAGE\n");
        f1ap_initial_ul_rrc_message_t *msg = &F1AP_INITIAL_UL_RRC_MESSAGE(received_msg);
        DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(0,0,0,msg->crnti,
                                                msg->rrc_container,
162
                                                msg->rrc_container_length,
163 164 165
                                                msg->du2cu_rrc_container,
                                                msg->du2cu_rrc_container_length
                                               );
166 167
        break;

168
      case F1AP_UL_RRC_MESSAGE: // to rrc
169
        LOG_I(F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n");
170

171
        if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_DU) {
172
          DU_send_UL_NR_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
Xue Song's avatar
Xue Song committed
173 174
                                             &F1AP_UL_RRC_MESSAGE(received_msg));
        } else {
175
          DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
Xue Song's avatar
Xue Song committed
176 177
                                          &F1AP_UL_RRC_MESSAGE(received_msg));
        }
178

179 180
        break;

181 182 183 184
      case F1AP_UE_CONTEXT_SETUP_RESP:
        DU_send_UE_CONTEXT_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_SETUP_RESP(received_msg));
        break;

185
      case F1AP_UE_CONTEXT_RELEASE_REQ: // from MAC
186
        LOG_I(F1AP, "DU Task Received F1AP_UE_CONTEXT_RELEASE_REQ\n");
187
        DU_send_UE_CONTEXT_RELEASE_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
188 189 190
                                           &F1AP_UE_CONTEXT_RELEASE_REQ(received_msg));
        break;

191
      case TERMINATE_MESSAGE:
192
        LOG_W(F1AP, " *** Exiting F1AP thread\n");
193 194 195 196
        itti_exit_task();
        break;

      default:
197 198
        LOG_E(F1AP, "DU Received unhandled message: %d:%s\n",
              ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
199 200
        break;
    } // switch
201

202 203 204 205 206 207
    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;
208
}