rlc_am_init.c 10.4 KB
Newer Older
1
/*******************************************************************************
gauthier's avatar
gauthier committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
gauthier's avatar
gauthier committed
27
28

 *******************************************************************************/
29
30
31
32
33
34
35
36
37
38
#define RLC_AM_MODULE
#define RLC_AM_INIT_C
#ifdef USER_MODE
#include <string.h>
#endif
//-----------------------------------------------------------------------------
#include "rlc_am.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
//-----------------------------------------------------------------------------
39
40
void
rlc_am_init(
41
42
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_am_entity_t *const        rlc_pP)
43
44
//-----------------------------------------------------------------------------
{
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  if (rlc_pP->initialized == TRUE) {
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] INITIALIZATION ALREADY DONE, DOING NOTHING\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP));
  } else {
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] INITIALIZATION: STATE VARIABLES, BUFFERS, LISTS\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP));
    memset(rlc_pP, 0, sizeof(rlc_am_entity_t));

    list2_init(&rlc_pP->receiver_buffer,      "RX BUFFER");
    list_init(&rlc_pP->pdus_to_mac_layer,     "PDUS TO MAC");
    list_init(&rlc_pP->control_pdu_list,      "CONTROL PDU LIST");
    list_init(&rlc_pP->segmentation_pdu_list, "SEGMENTATION PDU LIST");
    //LOG_D(RLC,"RLC_AM_SDU_CONTROL_BUFFER_SIZE %d sizeof(rlc_am_tx_sdu_management_t) %d \n",  RLC_AM_SDU_CONTROL_BUFFER_SIZE, sizeof(rlc_am_tx_sdu_management_t));

    pthread_mutex_init(&rlc_pP->lock_input_sdus, NULL);
    rlc_pP->input_sdus               = calloc(1, RLC_AM_SDU_CONTROL_BUFFER_SIZE*sizeof(rlc_am_tx_sdu_management_t));
61
#warning "cast the rlc retrans buffer to uint32"
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    //        rlc_pP->pdu_retrans_buffer       = calloc(1, (uint16_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t)));
    rlc_pP->pdu_retrans_buffer       = calloc(1, (uint32_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t)));
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] input_sdus[] = %p  element size=%d\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          rlc_pP->input_sdus,
          sizeof(rlc_am_tx_sdu_management_t));
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] pdu_retrans_buffer[] = %p element size=%d\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          rlc_pP->pdu_retrans_buffer,
          sizeof(rlc_am_tx_data_pdu_management_t));

    // TX state variables
    //rlc_pP->vt_a    = 0;
    rlc_pP->vt_ms   = rlc_pP->vt_a + RLC_AM_WINDOW_SIZE;
    //rlc_pP->vt_s    = 0;
    //rlc_pP->poll_sn = 0;
    // TX counters
    //rlc_pP->c_pdu_without_poll  = 0;
    //rlc_pP->c_byte_without_poll = 0;
    // RX state variables
    //rlc_pP->vr_r    = 0;
    rlc_pP->vr_mr   = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
    //rlc_pP->vr_x    = 0;
    //rlc_pP->vr_ms   = 0;
    //rlc_pP->vr_h    = 0;

    rlc_pP->last_frame_status_indication = 123456; // any value > 1
    rlc_pP->first_retrans_pdu_sn         = -1;

    rlc_pP->initialized                  = TRUE;
  }
93
}
94
//-----------------------------------------------------------------------------
95
96
void
rlc_am_reestablish(
97
98
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_am_entity_t* const        rlc_pP)
99
100
//-----------------------------------------------------------------------------
{
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  /*
   * RLC re-establishment is performed upon request by RRC, and the function
   * is applicable for AM, UM and TM RLC entities.
   * When RRC indicates that an RLC entity should be re-established, the RLC entity shall:
   * - if it is an AM RLC entity:
   *    - when possible, reassemble RLC SDUs from any byte segments of AMD PDUs with SN < VR(MR) in the
   *       receiving side, remove RLC headers when doing so and deliver all reassembled RLC SDUs to upper layer in
   *        ascending order of the RLC SN, if not delivered before;
   *    - discard the remaining AMD PDUs and byte segments of AMD PDUs in the receiving side;
   *    - discard all RLC SDUs and AMD PDUs in the transmitting side;
   *    - discard all RLC control PDUs.
   *    - stop and reset all timers;
   *    - reset all state variables to their initial values.
   */
  LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM REESTABLISH] RE-INIT STATE VARIABLES, BUFFERS, LISTS\n",
        PROTOCOL_CTXT_ARGS(ctxt_pP));
117
118

#warning TODO when possible reassemble RLC SDUs from any byte segments of AMD PDUs with SN inf VR(MR)
119
  list2_free(&rlc_pP->receiver_buffer);
120

121
122
123
  list_free(&rlc_pP->pdus_to_mac_layer);
  list_free(&rlc_pP->control_pdu_list);
  list_free(&rlc_pP->segmentation_pdu_list);
124
125


126
127
128
129
130
  // TX state variables
  rlc_pP->vt_a    = 0;
  rlc_pP->vt_ms   = rlc_pP->vt_a + RLC_AM_WINDOW_SIZE;
  rlc_pP->vt_s    = 0;
  rlc_pP->poll_sn = 0;
131

132
133
134
  // TX counters
  rlc_pP->c_pdu_without_poll  = 0;
  rlc_pP->c_byte_without_poll = 0;
135

136
137
138
139
140
141
  // RX state variables
  rlc_pP->vr_r    = 0;
  rlc_pP->vr_mr   = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
  rlc_pP->vr_x    = 0;
  rlc_pP->vr_ms   = 0;
  rlc_pP->vr_h    = 0;
142

143
144
  rlc_pP->last_frame_status_indication = 123456; // any value > 1
  rlc_pP->first_retrans_pdu_sn         = -1;
145

146
  rlc_pP->initialized                  = TRUE;
147
148
149

}

150
//-----------------------------------------------------------------------------
151
152
void
rlc_am_cleanup(
153
154
  rlc_am_entity_t* const        rlc_pP
)
155
156
//-----------------------------------------------------------------------------
{
157
158
159
  LOG_I(RLC, RB_AM_FMT"[CLEANUP %p]\n",
        RB_AM_ARGS(rlc_pP),
        rlc_pP);
gauthier's avatar
gauthier committed
160

161
162
163
164
  list2_free(&rlc_pP->receiver_buffer);
  list_free(&rlc_pP->pdus_to_mac_layer);
  list_free(&rlc_pP->control_pdu_list);
  list_free(&rlc_pP->segmentation_pdu_list);
gauthier's avatar
gauthier committed
165
166


167
168
169
170
171
172
173
174
175
176
177
178
179
  if (rlc_pP->output_sdu_in_construction != NULL) {
    free_mem_block(rlc_pP->output_sdu_in_construction);
    rlc_pP->output_sdu_in_construction = NULL;
  }

  unsigned int i;

  if (rlc_pP->input_sdus != NULL) {
    for (i=0; i < RLC_AM_SDU_CONTROL_BUFFER_SIZE; i++) {
      if (rlc_pP->input_sdus[i].mem_block != NULL) {
        free_mem_block(rlc_pP->input_sdus[i].mem_block);
        rlc_pP->input_sdus[i].mem_block = NULL;
      }
180
    }
181
182
183
184
185
186
187
188
189
190
191
192
193

    free(rlc_pP->input_sdus);
    rlc_pP->input_sdus       = NULL;
  }

  pthread_mutex_destroy(&rlc_pP->lock_input_sdus);

  if (rlc_pP->pdu_retrans_buffer != NULL) {
    for (i=0; i < RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE; i++) {
      if (rlc_pP->pdu_retrans_buffer[i].mem_block != NULL) {
        free_mem_block(rlc_pP->pdu_retrans_buffer[i].mem_block);
        rlc_pP->pdu_retrans_buffer[i].mem_block = NULL;
      }
194
    }
195
196
197
198
199
200

    free(rlc_pP->pdu_retrans_buffer);
    rlc_pP->pdu_retrans_buffer       = NULL;
  }

  memset(rlc_pP, 0, sizeof(rlc_am_entity_t));
201
202
}
//-----------------------------------------------------------------------------
203
204
void
rlc_am_configure(
205
206
207
208
209
210
211
212
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_am_entity_t *const        rlc_pP,
  const uint16_t                max_retx_thresholdP,
  const uint16_t                poll_pduP,
  const uint16_t                poll_byteP,
  const uint32_t                t_poll_retransmitP,
  const uint32_t                t_reorderingP,
  const uint32_t                t_status_prohibitP)
213
214
//-----------------------------------------------------------------------------
{
215
  if (rlc_pP->configured == TRUE) {
216
    LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB AM %u][RECONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n",
217
          PROTOCOL_CTXT_ARGS(ctxt_pP),
gauthier's avatar
gauthier committed
218
219
220
221
222
223
224
225
          rlc_pP->rb_id,
          max_retx_thresholdP,
          poll_pduP,
          poll_byteP,
          t_poll_retransmitP,
          t_reorderingP,
          t_status_prohibitP);

226
227
228
229
    rlc_pP->max_retx_threshold = max_retx_thresholdP;
    rlc_pP->poll_pdu           = poll_pduP;
    rlc_pP->poll_byte          = poll_byteP;
    rlc_pP->protocol_state     = RLC_DATA_TRANSFER_READY_STATE;
230

231
232
233
    rlc_pP->t_poll_retransmit.time_out   = t_poll_retransmitP;
    rlc_pP->t_reordering.time_out        = t_reorderingP;
    rlc_pP->t_status_prohibit.time_out   = t_status_prohibitP;
234
  } else {
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
    LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB AM %u][CONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          rlc_pP->rb_id,
          max_retx_thresholdP,
          poll_pduP,
          poll_byteP,
          t_poll_retransmitP,
          t_reorderingP,
          t_status_prohibitP);

    rlc_pP->max_retx_threshold = max_retx_thresholdP;
    rlc_pP->poll_pdu           = poll_pduP;
    rlc_pP->poll_byte          = poll_byteP;
    rlc_pP->protocol_state     = RLC_DATA_TRANSFER_READY_STATE;


    rlc_am_init_timer_poll_retransmit(ctxt_pP, rlc_pP, t_poll_retransmitP);
    rlc_am_init_timer_reordering     (ctxt_pP, rlc_pP, t_reorderingP);
    rlc_am_init_timer_status_prohibit(ctxt_pP, rlc_pP, t_status_prohibitP);

    rlc_pP->configured = TRUE;
256
  }
gauthier's avatar
gauthier committed
257

258
259
}
//-----------------------------------------------------------------------------
260
261
void
rlc_am_set_debug_infos(
262
263
264
265
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_am_entity_t *const        rlc_pP,
  const srb_flag_t              srb_flagP,
  const rb_id_t                 rb_idP)
266
267
//-----------------------------------------------------------------------------
{
268

269
270
271
272
273
274
275
276
277
278
279
  rlc_pP->rb_id         = rb_idP;

  if (srb_flagP) {
    rlc_pP->is_data_plane = 0;
  } else {
    rlc_pP->is_data_plane = 1;
  }

  LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT "[SET DEBUG INFOS]\n",
        PROTOCOL_CTXT_ARGS(ctxt_pP),
        RB_AM_ARGS(rlc_pP));
280

281
}