Exemplo n.º 1
0
void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
{
  s1ap_eNB_instance_t *instance_p;
  s1ap_eNB_mme_data_t *s1ap_mme_data_p;

  DevAssert(sctp_new_association_resp != NULL);

  instance_p = s1ap_eNB_get_instance(instance);
  DevAssert(instance_p != NULL);

  s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1,
                                     sctp_new_association_resp->ulp_cnx_id);
  DevAssert(s1ap_mme_data_p != NULL);

  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
    S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
              sctp_new_association_resp->sctp_state,
              instance,
              sctp_new_association_resp->ulp_cnx_id);

    s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);

    return;
  }

  /* Update parameters */
  s1ap_mme_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
  s1ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
  s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;

  /* Prepare new S1 Setup Request */
  s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p);
}
static
int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
                                     uint32_t               stream,
                                     struct s1ap_message_s *message_p)
{
  S1ap_S1SetupFailureIEs_t   *s1_setup_failure_p;
  s1ap_eNB_mme_data_t        *mme_desc_p;

  DevAssert(message_p != NULL);

  s1_setup_failure_p = &message_p->msg.s1ap_S1SetupFailureIEs;

  /* S1 Setup Failure == Non UE-related procedure -> stream 0 */
  if (stream != 0) {
    S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
              assoc_id, stream);
  }

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
               "MME context\n", assoc_id);
    return -1;
  }

  if ((s1_setup_failure_p->cause.present == S1ap_Cause_PR_misc) &&
      (s1_setup_failure_p->cause.choice.misc == S1ap_CauseMisc_unspecified)) {
    S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n");
  } else {
    S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
  }

  mme_desc_p->state = S1AP_ENB_STATE_WAITING;
  s1ap_handle_s1_setup_message(mme_desc_p, 0);

  return 0;
}
static
int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
                                      uint32_t               stream,
                                      struct s1ap_message_s *message_p)
{
  S1ap_S1SetupResponseIEs_t *s1SetupResponse_p;
  s1ap_eNB_mme_data_t       *mme_desc_p;
  int i;

  DevAssert(message_p != NULL);

  s1SetupResponse_p = &message_p->msg.s1ap_S1SetupResponseIEs;

  /* S1 Setup Response == Non UE-related procedure -> stream 0 */
  if (stream != 0) {
    S1AP_ERROR("[SCTP %d] Received s1 setup response on stream != 0 (%d)\n",
               assoc_id, stream);
    return -1;
  }

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
               "MME context\n", assoc_id);
    return -1;
  }

  /* The list of served gummei can contain at most 8 elements.
   * LTE related gummei is the first element in the list, i.e with an id of 0.
   */
  DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count == 1);

  for (i = 0; i < s1SetupResponse_p->servedGUMMEIs.list.count; i++) {
    struct S1ap_ServedGUMMEIsItem *gummei_item_p;
    struct served_gummei_s        *new_gummei_p;
    int j;

    gummei_item_p = (struct S1ap_ServedGUMMEIsItem *)
                    s1SetupResponse_p->servedGUMMEIs.list.array[i];
    new_gummei_p = calloc(1, sizeof(struct served_gummei_s));

    STAILQ_INIT(&new_gummei_p->served_plmns);
    STAILQ_INIT(&new_gummei_p->served_group_ids);
    STAILQ_INIT(&new_gummei_p->mme_codes);

    for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) {
      S1ap_PLMNidentity_t *plmn_identity_p;
      struct plmn_identity_s *new_plmn_identity_p;

      plmn_identity_p = gummei_item_p->servedPLMNs.list.array[i];
      new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s));
      TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc,
                      new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length);
      STAILQ_INSERT_TAIL(&new_gummei_p->served_plmns, new_plmn_identity_p, next);
      new_gummei_p->nb_served_plmns++;
    }

    for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) {
      S1ap_MME_Group_ID_t           *mme_group_id_p;
      struct served_group_id_s *new_group_id_p;

      mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[i];
      new_group_id_p = calloc(1, sizeof(struct served_group_id_s));
      OCTET_STRING_TO_INT16(mme_group_id_p, new_group_id_p->mme_group_id);
      STAILQ_INSERT_TAIL(&new_gummei_p->served_group_ids, new_group_id_p, next);
      new_gummei_p->nb_group_id++;
    }

    for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) {
      S1ap_MME_Code_t        *mme_code_p;
      struct mme_code_s *new_mme_code_p;

      mme_code_p = gummei_item_p->servedMMECs.list.array[i];
      new_mme_code_p = calloc(1, sizeof(struct mme_code_s));

      OCTET_STRING_TO_INT8(mme_code_p, new_mme_code_p->mme_code);
      STAILQ_INSERT_TAIL(&new_gummei_p->mme_codes, new_mme_code_p, next);
      new_gummei_p->nb_mme_code++;
    }

    STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next);
  }

  /* Free contents of the list */
  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1ap_ServedGUMMEIs,
                                (void *)&s1SetupResponse_p->servedGUMMEIs);
  /* Set the capacity of this MME */
  mme_desc_p->relative_mme_capacity = s1SetupResponse_p->relativeMMECapacity;

  /* Optionaly set the mme name */
  if (s1SetupResponse_p->presenceMask & S1AP_S1SETUPRESPONSEIES_MMENAME_PRESENT) {
    mme_desc_p->mme_name = calloc(s1SetupResponse_p->mmEname.size + 1, sizeof(char));
    memcpy(mme_desc_p->mme_name, s1SetupResponse_p->mmEname.buf,
           s1SetupResponse_p->mmEname.size);
    /* Convert the mme name to a printable string */
    mme_desc_p->mme_name[s1SetupResponse_p->mmEname.size] = '\0';
  }

  /* The association is now ready as eNB and MME know parameters of each other.
   * Mark the association as UP to enable UE contexts creation.
   */
  mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
  mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++;
  s1ap_handle_s1_setup_message(mme_desc_p, 0);

#if 0
  /* We call back our self
   * -> generate a dummy initial UE message
   */
  {
    s1ap_nas_first_req_t s1ap_nas_first_req;

    memset(&s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t));

    s1ap_nas_first_req.rnti = 0xC03A;
    s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA;
    s1ap_nas_first_req.ue_identity.presenceMask = UE_IDENTITIES_gummei;

    s1ap_nas_first_req.ue_identity.gummei.mcc = 208;
    s1ap_nas_first_req.ue_identity.gummei.mnc = 34;
    s1ap_nas_first_req.ue_identity.gummei.mme_code = 0;
    s1ap_nas_first_req.ue_identity.gummei.mme_group_id = 0;

    /* NAS Attach request with IMSI */
    static uint8_t nas_attach_req_imsi[] = {
      0x07, 0x41,
      /* EPS Mobile identity = IMSI */
      0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
      0xF9,
      /* End of EPS Mobile Identity */
      0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
      0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
      0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
      0x01, 0x27, 0x11,
    };

    /* NAS Attach request with GUTI */
    static uint8_t nas_attach_req_guti[] = {
      0x07, 0x41,
      /* EPS Mobile identity = IMSI */
      0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
      0xDA, 0x1F,
      /* End of EPS Mobile Identity */
      0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
      0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
      0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
      0x01, 0x27, 0x11,
    };

    s1ap_nas_first_req.nas_pdu.buffer = nas_attach_req_guti;
    s1ap_nas_first_req.nas_pdu.length = sizeof(nas_attach_req_guti);

    s1ap_eNB_handle_nas_first_req(mme_desc_p->s1ap_eNB_instance->instance,
                                  &s1ap_nas_first_req);
  }
#endif

  return 0;
}