rlc_tm.c 9.04 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.0  (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
23
#define RLC_TM_MODULE 1
#define RLC_TM_C 1
24
25
26
27
28
29
30
31
32
33
34
//-----------------------------------------------------------------------------
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
#include "rlc_tm.h"
#include "mac_primitives.h"
#include "rlc_primitives.h"
#include "list.h"
#include "LAYER2/MAC/extern.h"
//-----------------------------------------------------------------------------
void
35
rlc_tm_send_sdu (
36
37
38
39
40
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_tm_entity_t * const rlc_pP,
  const boolean_t         error_indicationP,
  uint8_t * const         srcP,
  const sdu_size_t        length_in_bitsP)
41
{
42
  int             length_in_bytes;
43
#if DEBUG_RLC_TM_DISPLAY_ASCII_DATA
44
45
  int             index;
#endif
46
#if DEBUG_RLC_TM_REASSEMBLY
47
48
49
  LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT"[SEND_SDU] %d bits\n",
        PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_pP),
        length_in_bitsP);
50
51
52
53
#endif
  length_in_bytes = (length_in_bitsP + 7) >> 3;

  if (rlc_pP->output_sdu_in_construction == NULL) {
54
    rlc_pP->output_sdu_in_construction = get_free_mem_block (length_in_bytes, __func__);
55
56
57
  }

  if ((rlc_pP->output_sdu_in_construction)) {
58
#if DEBUG_RLC_TM_DISPLAY_ASCII_DATA
59
60
    LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT"[SEND_SDU] DATA :",
          PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_pP));
61
62
63

    for (index = 0; index < length_in_bytes; index++) {
      msg ("%c", srcP[index]);
64
    }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

    msg ("\n");
#endif

    memcpy (&rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write], srcP, length_in_bytes);

    rlc_data_ind (
      ctxt_pP,
      BOOL_NOT(rlc_pP->is_data_plane),
      MBMS_FLAG_NO,
      rlc_pP->rb_id,
      length_in_bytes,
      rlc_pP->output_sdu_in_construction);
    rlc_pP->output_sdu_in_construction = NULL;
  } else {
    msg ("[RLC_TM %p][SEND_SDU] ERROR  OUTPUT SDU IS NULL\n", rlc_pP);
  }
82
83
84
}
//-----------------------------------------------------------------------------
void
85
rlc_tm_no_segment (
86
87
88
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_tm_entity_t *const rlc_pP
)
89
{
90
91
92
93
94
95
96
97
98
99
  mem_block_t                     *pdu_p               = NULL;
  struct rlc_tm_tx_sdu_management *sdu_mngt_p          = NULL;
  struct rlc_tm_tx_pdu_management *pdu_mngt_p          = NULL;
  int                              nb_pdu_to_transmit  = 1;

  // only one SDU per TTI
  while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index]) && (nb_pdu_to_transmit > 0)) {

    sdu_mngt_p = ((struct rlc_tm_tx_sdu_management *) (rlc_pP->input_sdus[rlc_pP->current_sdu_index]->data));

100
    if (!(pdu_p = get_free_mem_block (((rlc_pP->rlc_pdu_size + 7) >> 3) + sizeof (struct rlc_tm_tx_data_pdu_struct) + GUARD_CRC_LIH_SIZE, __func__))) {
101
102
      LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT"[SEGMENT] ERROR COULD NOT GET NEW PDU, EXIT\n",
            PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_pP));
103
      return;
104
    }
105
106
107
108
109
110
111
112
113
114
115
116
117
118

    // SHOULD BE OPTIMIZED...SOON
    pdu_mngt_p = (struct rlc_tm_tx_pdu_management *) (pdu_p->data);
    memset (pdu_p->data, 0, sizeof (struct rlc_tm_tx_pdu_management));
    pdu_mngt_p->first_byte = (uint8_t*)&pdu_p->data[sizeof (struct rlc_tm_tx_data_pdu_struct)];

    memcpy (pdu_mngt_p->first_byte, sdu_mngt_p->first_byte, ((rlc_pP->rlc_pdu_size + 7) >> 3));
    ((struct mac_tb_req *) (pdu_p->data))->rlc = NULL;
    ((struct mac_tb_req *) (pdu_p->data))->data_ptr = pdu_mngt_p->first_byte;
    ((struct mac_tb_req *) (pdu_p->data))->first_bit = 0;
    ((struct mac_tb_req *) (pdu_p->data))->tb_size = rlc_pP->rlc_pdu_size >> 3;
    list_add_tail_eurecom (pdu_p, &rlc_pP->pdus_to_mac_layer);

    rlc_pP->buffer_occupancy -= (sdu_mngt_p->sdu_size >> 3);
119
    free_mem_block (rlc_pP->input_sdus[rlc_pP->current_sdu_index], __func__);
120
121
122
123
    rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
    rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % rlc_pP->size_input_sdus_buffer;
    rlc_pP->nb_sdu -= 1;
  }
124
125
126
}
//-----------------------------------------------------------------------------
void
127
rlc_tm_rx (
128
129
130
  const protocol_ctxt_t* const  ctxt_pP,
  void * const         argP,
  struct mac_data_ind data_indP)
131
132
{

133
134
135
  rlc_tm_entity_t     * const rlc_p = (rlc_tm_entity_t *) argP;
  mem_block_t         *tb_p;
  uint8_t             *first_byte_p;
136

137
  rlc_p->output_sdu_size_to_write = 0;      // size of sdu reassemblied
138

139
140
  while ((tb_p = list_remove_head (&data_indP.data))) {
    first_byte_p = ((struct mac_tb_ind *) (tb_p->data))->data_ptr;
141

142
143
144
    ((struct rlc_tm_rx_pdu_management *) (tb_p->data))->first_byte = first_byte_p;

    rlc_tm_send_sdu (ctxt_pP, rlc_p, (((struct mac_tb_ind *) (tb_p->data))->error_indication), first_byte_p, data_indP.tb_size);
145
    free_mem_block (tb_p, __func__);
146
  }
147
148
149
150
}

//-----------------------------------------------------------------------------
struct mac_status_resp
151
rlc_tm_mac_status_indication (
152
153
154
155
  const protocol_ctxt_t* const  ctxt_pP,
  void * const                  rlc_pP,
  const tb_size_t               tb_sizeP,
  struct mac_status_ind         tx_statusP)
156
157
158
{
  struct mac_status_resp status_resp;

159
  ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size = tb_sizeP;
160

161
162
163
  status_resp.buffer_occupancy_in_bytes = ((rlc_tm_entity_t *) rlc_pP)->buffer_occupancy;
  status_resp.buffer_occupancy_in_pdus = status_resp.buffer_occupancy_in_bytes / ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size;
  status_resp.rlc_info.rlc_protocol_state = ((rlc_tm_entity_t *) rlc_pP)->protocol_state;
164
165
166
167
168
  return status_resp;
}

//-----------------------------------------------------------------------------
struct mac_data_req
169
rlc_tm_mac_data_request (
170
171
  const protocol_ctxt_t* const  ctxt_pP,
  void * const rlc_pP)
172
{
173
  rlc_tm_entity_t*    rlc_p = (rlc_tm_entity_t*) rlc_pP;
174
175
  struct mac_data_req data_req;

176
  rlc_tm_no_segment (ctxt_pP, rlc_p);
177
  list_init (&data_req.data, NULL);
178
179
180
181
  list_add_list (&rlc_p->pdus_to_mac_layer, &data_req.data);
  data_req.buffer_occupancy_in_bytes = rlc_p->buffer_occupancy;
  data_req.buffer_occupancy_in_pdus = data_req.buffer_occupancy_in_bytes / rlc_p->rlc_pdu_size;
  data_req.rlc_info.rlc_protocol_state = rlc_p->protocol_state;
182

183
  if (data_req.data.nb_elements > 0) {
184
185
    LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" MAC_DATA_REQUEST %d TBs\n",
          PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
186
          data_req.data.nb_elements);
187
188
189
190
191
192
193
  }

  return data_req;
}

//-----------------------------------------------------------------------------
void
194
rlc_tm_mac_data_indication (
195
196
197
  const protocol_ctxt_t* const  ctxt_pP,
  void * const        rlc_pP,
  struct mac_data_ind data_indP)
198
{
199
  rlc_tm_entity_t* rlc_p = (rlc_tm_entity_t*) rlc_pP;
200
201

  if (data_indP.data.nb_elements > 0) {
202
203
    LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" MAC_DATA_IND %d TBs\n",
          PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
204
205
206
207
          data_indP.data.nb_elements);
  }

  rlc_tm_rx (ctxt_pP, rlc_pP, data_indP);
208
209
210
211
}

//-----------------------------------------------------------------------------
void
212
rlc_tm_data_req (
213
214
215
  const protocol_ctxt_t* const  ctxt_pP,
  void *const rlc_pP,
  mem_block_t *const sdu_pP)
216
{
217
  rlc_tm_entity_t *rlc_p = (rlc_tm_entity_t *) rlc_pP;
218

219
#if DEBUG_RLC_TM_DATA_REQUEST
220
221
  LOG_D (RLC, PROTOCOL_RLC_TM_CTXT_FMT" RLC_TM_DATA_REQ size %d Bytes, BO %ld , NB SDU %d current_sdu_index=%d next_sdu_index=%d\n",
         PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
222
223
224
225
         ((struct rlc_um_data_req *) (sdu_pP->data))->data_size,
         rlc_p->buffer_occupancy,
         rlc_p->nb_sdu,
         rlc_p->current_sdu_index,
226
227
         rlc_p->next_sdu_index);
#endif
228
229

  // not in 3GPP specification but the buffer may be full if not correctly configured
230
231
232
233
234
235
236
  if (rlc_p->input_sdus[rlc_p->next_sdu_index] == NULL) {
    ((struct rlc_tm_tx_sdu_management *) (sdu_pP->data))->sdu_size = ((struct rlc_tm_data_req *) (sdu_pP->data))->data_size;
    rlc_p->buffer_occupancy += ((struct rlc_tm_tx_sdu_management *) (sdu_pP->data))->sdu_size >> 3;
    rlc_p->nb_sdu += 1;
    ((struct rlc_tm_tx_sdu_management *) (sdu_pP->data))->first_byte = (uint8_t*)&sdu_pP->data[sizeof (struct rlc_tm_data_req_alloc)];
    rlc_p->input_sdus[rlc_p->next_sdu_index] = sdu_pP;
    rlc_p->next_sdu_index = (rlc_p->next_sdu_index + 1) % rlc_p->size_input_sdus_buffer;
237
  } else {
238
    free_mem_block (sdu_pP, __func__);
239
240
  }
}