//-----------------------------------------------------------------------------
void
send_rlc_um_control_primitive (struct rlc_um_entity *rlcP, struct mem_block *cprimitiveP)
{
//-----------------------------------------------------------------------------

  switch (((struct crlc_primitive *) cprimitiveP->data)->type) {

      case CRLC_CONFIG_REQ:

        switch (((struct crlc_primitive *) cprimitiveP->data)->primitive.c_config_req.parameters.um_parameters.e_r) {

            case RLC_E_R_ESTABLISHMENT:
              if (rlc_um_fsm_notify_event (rlcP, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
                rlc_um_set_configured_parameters (rlcP, cprimitiveP);   // the order of the calling of procedures...
                rlc_um_reset_state_variables (rlcP);    // ...must not ...
              }
              break;

            case RLC_E_R_MODIFICATION:
              msg ("[RLC_UM][ERROR] send_rlc_um_control_primitive(CRLC_CONFIG_REQ) RLC_AM_E_R_MODIFICATION not handled\n");
              break;

            case RLC_E_R_RELEASE:
              if (rlc_um_fsm_notify_event (rlcP, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_NULL_STATE_EVENT)) {
                rlc_um_free_all_resources (rlcP);
              }
              break;

            default:
              msg ("[RLC_UM][ERROR] send_rlc_um_control_primitive(CRLC_CONFIG_REQ) unknown parameter E_R\n");
        }
        break;

      case CRLC_RESUME_REQ:
        msg ("[RLC_UM][ERROR] send_rlc_um_control_primitive(CRLC_RESUME_REQ) cprimitive not handled\n");
        break;

      default:
        msg ("[RLC_UM %p][ERROR] send_rlc_um_control_primitive(UNKNOWN CPRIMITIVE)\n", rlcP);
  }
  free_mem_block (cprimitiveP);
}
//-----------------------------------------------------------------------------
void rlc_um_configure(
    rlc_um_entity_t * const rlc_pP,
    const frame_t          frameP,
    const uint32_t         timer_reorderingP,
    const uint32_t         rx_sn_field_lengthP,
    const uint32_t         tx_sn_field_lengthP,
    const uint32_t         is_mXchP)
//-----------------------------------------------------------------------------
{
  if (rx_sn_field_lengthP == 10) {
      rlc_pP->rx_sn_length                  = 10;
      rlc_pP->rx_sn_modulo                  = RLC_UM_SN_10_BITS_MODULO;
      rlc_pP->rx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_10_BITS;
      rlc_pP->rx_header_min_length_in_bytes = 2;
  } else if (rx_sn_field_lengthP == 5) {
      rlc_pP->rx_sn_length                  = 5;
      rlc_pP->rx_sn_modulo                  = RLC_UM_SN_5_BITS_MODULO;
      rlc_pP->rx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_5_BITS;
      rlc_pP->rx_header_min_length_in_bytes = 1;
  } else if (rx_sn_field_lengthP != 0) {
      LOG_E(RLC, "[FRAME %05d][%s][RLC_UM][MOD %u/%u][RB %u][CONFIGURE] INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
          frameP,
          (rlc_pP->is_enb) ? "eNB" : "UE",
              rlc_pP->enb_module_id,
              rlc_pP->ue_module_id,
              rlc_pP->rb_id,
              rx_sn_field_lengthP);
      return;
  }

  if (tx_sn_field_lengthP == 10) {
      rlc_pP->tx_sn_length                  = 10;
      rlc_pP->tx_sn_modulo                  = RLC_UM_SN_10_BITS_MODULO;
      rlc_pP->tx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_10_BITS;
      rlc_pP->tx_header_min_length_in_bytes = 2;
  } else if (tx_sn_field_lengthP == 5) {
      rlc_pP->tx_sn_length                  = 5;
      rlc_pP->tx_sn_modulo                  = RLC_UM_SN_5_BITS_MODULO;
      rlc_pP->tx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_5_BITS;
      rlc_pP->tx_header_min_length_in_bytes = 1;
  } else if (tx_sn_field_lengthP != 0) {
      LOG_E(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02d/%02][RB %u][CONFIGURE] INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
          frameP,
          (rlc_pP->is_enb) ? "eNB" : "UE",
              rlc_pP->enb_module_id,
              rlc_pP->ue_module_id,
              rlc_pP->rb_id,
              tx_sn_field_lengthP);
      return;
  }

  if (is_mXchP > 0) {
      rlc_pP->tx_um_window_size = 0;
      rlc_pP->rx_um_window_size = 0;
  }
  rlc_pP->is_mxch = is_mXchP;

  rlc_pP->last_reassemblied_sn  = rlc_pP->rx_sn_modulo - 1;
  rlc_pP->last_reassemblied_missing_sn  = rlc_pP->rx_sn_modulo - 1;
  rlc_pP->reassembly_missing_sn_detected = 0;
  // timers
  rlc_um_init_timer_reordering(rlc_pP, timer_reorderingP);

  rlc_pP->first_pdu = 1;

  rlc_um_reset_state_variables (rlc_pP);
}
//-----------------------------------------------------------------------------
void rlc_um_configure(
  const protocol_ctxt_t* const ctxt_pP,
  rlc_um_entity_t * const rlc_pP,
  const uint32_t         timer_reorderingP,
  const uint32_t         rx_sn_field_lengthP,
  const uint32_t         tx_sn_field_lengthP,
  const uint32_t         is_mXchP)
{
  if (rx_sn_field_lengthP == 10) {
    rlc_pP->rx_sn_length                  = 10;
    rlc_pP->rx_sn_modulo                  = RLC_UM_SN_10_BITS_MODULO;
    rlc_pP->rx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_10_BITS;
    rlc_pP->rx_header_min_length_in_bytes = 2;
  } else if (rx_sn_field_lengthP == 5) {
    rlc_pP->rx_sn_length                  = 5;
    rlc_pP->rx_sn_modulo                  = RLC_UM_SN_5_BITS_MODULO;
    rlc_pP->rx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_5_BITS;
    rlc_pP->rx_header_min_length_in_bytes = 1;
  } else if (rx_sn_field_lengthP != 0) {
    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
          PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
          rlc_pP->rb_id,
          rx_sn_field_lengthP);
    return;
  }

  if (tx_sn_field_lengthP == 10) {
    rlc_pP->tx_sn_length                  = 10;
    rlc_pP->tx_sn_modulo                  = RLC_UM_SN_10_BITS_MODULO;
    rlc_pP->tx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_10_BITS;
    rlc_pP->tx_header_min_length_in_bytes = 2;
  } else if (tx_sn_field_lengthP == 5) {
    rlc_pP->tx_sn_length                  = 5;
    rlc_pP->tx_sn_modulo                  = RLC_UM_SN_5_BITS_MODULO;
    rlc_pP->tx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_5_BITS;
    rlc_pP->tx_header_min_length_in_bytes = 1;
  } else if (tx_sn_field_lengthP != 0) {
    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
          PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
          rlc_pP->rb_id,
          tx_sn_field_lengthP);
    return;
  }

  if (is_mXchP > 0) {
    rlc_pP->tx_um_window_size = 0;
    rlc_pP->rx_um_window_size = 0;
  }

  rlc_pP->is_mxch = is_mXchP;

  rlc_pP->last_reassemblied_sn  = rlc_pP->rx_sn_modulo - 1;
  rlc_pP->last_reassemblied_missing_sn  = rlc_pP->rx_sn_modulo - 1;
  rlc_pP->reassembly_missing_sn_detected = 0;
  // timers
  rlc_um_init_timer_reordering(ctxt_pP,rlc_pP, timer_reorderingP);

  rlc_pP->first_pdu = 1;

  rlc_um_reset_state_variables (ctxt_pP,rlc_pP);
}