blob: ad10b3abf0dbeedfdb209a0830cc2dedb2590d51 [file] [log] [blame]
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +02001/* rlc header descriptions
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20#pragma once
21
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010022#include "gprs_coding_scheme.h"
23
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +010024#include <osmocom/core/endian.h>
25
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020026#include <stdint.h>
27
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +010028#define RLC_GPRS_SNS 128 /* GPRS, must be power of 2 */
29#define RLC_GPRS_WS 64 /* max window size */
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +010030#define RLC_EGPRS_MIN_WS 64 /* min window size */
31#define RLC_EGPRS_MAX_WS 1024 /* min window size */
32#define RLC_EGPRS_SNS 2048 /* EGPRS, must be power of 2 */
Jacob Erlbeckd6752492016-02-02 18:12:46 +010033#define RLC_EGPRS_MAX_BSN_DELTA 512
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +010034#define RLC_MAX_SNS RLC_EGPRS_SNS
Jacob Erlbeckeb08f862016-02-05 17:07:12 +010035#define RLC_MAX_WS RLC_EGPRS_MAX_WS
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +010036#define RLC_MAX_LEN 74 /* MCS-9 data unit */
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010037
Holger Hans Peter Freyther35cc1c02014-07-02 14:48:44 +020038struct BTS;
Holger Hans Peter Freythercbb00eb2013-11-25 23:26:06 +010039struct gprs_rlc_v_n;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010040
Daniel Willmannd54d9f52013-12-28 21:16:13 +010041/* The state of a BSN in the send/receive window */
42enum gprs_rlc_ul_bsn_state {
43 GPRS_RLC_UL_BSN_INVALID,
44 GPRS_RLC_UL_BSN_RECEIVED,
45 GPRS_RLC_UL_BSN_MISSING,
46 GPRS_RLC_UL_BSN_MAX,
47};
48
49enum gprs_rlc_dl_bsn_state {
50 GPRS_RLC_DL_BSN_INVALID,
51 GPRS_RLC_DL_BSN_NACKED,
52 GPRS_RLC_DL_BSN_ACKED,
53 GPRS_RLC_DL_BSN_UNACKED,
54 GPRS_RLC_DL_BSN_RESEND,
55 GPRS_RLC_DL_BSN_MAX,
56};
57
Aravind Sirsikar7a05b032016-03-23 18:29:45 +053058/*
59 * Valid puncturing scheme values
60 * TS 44.060 10.4.8a.3.1, 10.4.8a.2.1, 10.4.8a.1.1
61 */
62enum egprs_puncturing_values {
63 EGPRS_PS_1,
64 EGPRS_PS_2,
65 EGPRS_PS_3,
66 EGPRS_PS_INVALID,
67};
68
69/*
70 * EGPRS_MAX_PS_NUM_2 is valid for MCS 1,2,5,6.
71 * And EGPRS_MAX_PS_NUM_3 is valid for MCS 3,4,7,8,9
72 * TS 44.060 10.4.8a.3.1, 10.4.8a.2.1, 10.4.8a.1.1
73 */
74enum egprs_puncturing_types {
75 EGPRS_MAX_PS_NUM_2 = 2,
76 EGPRS_MAX_PS_NUM_3,
77 EGPRS_MAX_PS_NUM_INVALID,
78};
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +010079
80static inline uint16_t mod_sns_half()
81{
82 return (RLC_MAX_SNS / 2) - 1;
83}
84
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +010085struct gprs_rlc_data_block_info {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010086 unsigned int data_len; /* EGPRS: N2, GPRS: N2-2, N-2 */
87 unsigned int bsn;
88 unsigned int ti;
89 unsigned int e;
Jacob Erlbeckcc34a5b2016-01-11 12:53:08 +010090 unsigned int cv; /* FBI == 1 <=> CV == 0 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010091 unsigned int pi;
92 unsigned int spb;
93};
94
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +010095struct gprs_rlc_data_info {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010096 GprsCodingScheme cs;
97 unsigned int r;
98 unsigned int si;
99 unsigned int tfi;
100 unsigned int cps;
101 unsigned int rsb;
Jacob Erlbeckcc34a5b2016-01-11 12:53:08 +0100102 unsigned int usf;
103 unsigned int es_p;
104 unsigned int rrbp;
105 unsigned int pr;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100106 unsigned int num_data_blocks;
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100107 unsigned int with_padding;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100108 unsigned int data_offs_bits[2];
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100109 struct gprs_rlc_data_block_info block_info[2];
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100110};
111
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100112struct gprs_rlc_data {
113 uint8_t *prepare(size_t block_data_length);
Holger Hans Peter Freyther423dd222013-11-25 23:24:29 +0100114 void put_data(const uint8_t *data, size_t len);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100115
Alexander Couzens68e2c632016-05-30 19:53:13 +0200116 /* block data including LI headers */
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100117 uint8_t block[RLC_MAX_LEN];
Alexander Couzens68e2c632016-05-30 19:53:13 +0200118 /* block data len including LI headers*/
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100119 uint8_t len;
Jacob Erlbeck1751c622015-06-04 12:12:32 +0200120
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100121 struct gprs_rlc_data_block_info block_info;
Jacob Erlbeckce1beb42015-12-14 12:04:01 +0100122 GprsCodingScheme cs;
Aravind Sirsikar7a05b032016-03-23 18:29:45 +0530123
124 /* puncturing scheme value to be used for next transmission*/
125 enum egprs_puncturing_values next_ps;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100126};
127
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +0100128void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100129 GprsCodingScheme cs, bool with_padding);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +0100130void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100131 GprsCodingScheme cs, bool with_padding);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +0100132void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100133 GprsCodingScheme cs, bool with_padding);
Aravind Sirsikara859a212016-03-23 18:29:46 +0530134unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, enum egprs_puncturing_values
135 punct, enum egprs_puncturing_values punct2, int with_padding);
Jacob Erlbeckfbd82e42016-02-03 18:31:19 +0100136void gprs_rlc_mcs_cps_decode(unsigned int cps, GprsCodingScheme cs,
137 int *punct, int *punct2, int *with_padding);
Aravind Sirsikar79522822016-03-23 18:29:47 +0530138enum egprs_puncturing_values gprs_get_punct_scheme(enum egprs_puncturing_values
139 punct, const GprsCodingScheme &cs,
140 const GprsCodingScheme &cs_current_trans);
141void gprs_update_punct_scheme(enum egprs_puncturing_values *punct,
142 const GprsCodingScheme &cs);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100143/*
144 * I hold the currently transferred blocks and will provide
145 * the routines to manipulate these arrays.
146 */
147struct gprs_rlc {
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100148 gprs_rlc_data *block(int bsn);
149 gprs_rlc_data m_blocks[RLC_MAX_SNS/2];
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100150};
151
Daniel Willmann146514e2013-12-28 18:24:42 +0100152/**
153 * TODO: for GPRS/EDGE maybe make sns a template parameter
154 * so we create specialized versions...
155 */
156struct gprs_rlc_v_b {
157 /* Check for an individual frame */
158 bool is_unacked(int bsn) const;
159 bool is_nacked(int bsn) const;
160 bool is_acked(int bsn) const;
161 bool is_resend(int bsn) const;
162 bool is_invalid(int bsn) const;
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100163 gprs_rlc_dl_bsn_state get_state(int bsn) const;
Daniel Willmann146514e2013-12-28 18:24:42 +0100164
165 /* Mark a RLC frame for something */
166 void mark_unacked(int bsn);
167 void mark_nacked(int bsn);
168 void mark_acked(int bsn);
169 void mark_resend(int bsn);
170 void mark_invalid(int bsn);
171
172 void reset();
173
174
175private:
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100176 bool is_state(int bsn, const gprs_rlc_dl_bsn_state state) const;
177 void mark(int bsn, const gprs_rlc_dl_bsn_state state);
Daniel Willmann146514e2013-12-28 18:24:42 +0100178
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100179 gprs_rlc_dl_bsn_state m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
Daniel Willmann146514e2013-12-28 18:24:42 +0100180};
181
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100182
183/**
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100184 * TODO: The UL/DL code could/should share a base class.
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100185 */
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100186class gprs_rlc_window {
187public:
188 gprs_rlc_window();
189
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100190 const uint16_t mod_sns() const;
Jacob Erlbeck93c55d02015-12-23 16:29:07 +0100191 const uint16_t mod_sns(uint16_t bsn) const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100192 const uint16_t sns() const;
193 const uint16_t ws() const;
194
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100195 void set_sns(uint16_t sns);
196 void set_ws(uint16_t ws);
197
198protected:
199 uint16_t m_sns;
200 uint16_t m_ws;
201};
202
203struct gprs_rlc_dl_window: public gprs_rlc_window {
204 void reset();
205
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100206 bool window_stalled() const;
207 bool window_empty() const;
208
209 void increment_send();
210 void raise(int moves);
211
212 const uint16_t v_s() const;
213 const uint16_t v_s_mod(int offset) const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100214 const uint16_t v_a() const;
215 const int16_t distance() const;
216
Daniel Willmann146514e2013-12-28 18:24:42 +0100217 /* Methods to manage reception */
218 int resend_needed();
219 int mark_for_resend();
Jacob Erlbecke1ca87f2015-12-23 16:40:56 +0100220 void update(BTS *bts, char *show_rbb, uint16_t ssn,
Daniel Willmann146514e2013-12-28 18:24:42 +0100221 uint16_t *lost, uint16_t *received);
Jacob Erlbeckeb08f862016-02-05 17:07:12 +0100222 void update(BTS *bts, const struct bitvec *rbb,
223 uint16_t first_bsn, uint16_t *lost,
224 uint16_t *received);
Daniel Willmann146514e2013-12-28 18:24:42 +0100225 int move_window();
Daniel Willmann3ce011f2014-01-15 12:45:56 +0100226 void show_state(char *show_rbb);
Daniel Willmann146514e2013-12-28 18:24:42 +0100227 int count_unacked();
228
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100229 uint16_t m_v_s; /* send state */
230 uint16_t m_v_a; /* ack state */
Daniel Willmann146514e2013-12-28 18:24:42 +0100231
232 gprs_rlc_v_b m_v_b;
Jacob Erlbecka3a567e2015-12-28 13:46:32 +0100233
234 gprs_rlc_dl_window();
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100235};
236
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100237struct gprs_rlc_v_n {
238 void reset();
239
240 void mark_received(int bsn);
241 void mark_missing(int bsn);
242
243 bool is_received(int bsn) const;
244
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100245 gprs_rlc_ul_bsn_state state(int bsn) const;
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100246private:
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100247 bool is_state(int bsn, const gprs_rlc_ul_bsn_state state) const;
248 void mark(int bsn, const gprs_rlc_ul_bsn_state state);
249 gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100250};
251
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100252struct gprs_rlc_ul_window: public gprs_rlc_window {
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100253 const uint16_t v_r() const;
254 const uint16_t v_q() const;
255
Daniel Willmann8a31f9e2013-11-27 17:08:35 +0100256 const uint16_t ssn() const;
257
Jacob Erlbecke1ca87f2015-12-23 16:40:56 +0100258 bool is_in_window(uint16_t bsn) const;
259 bool is_received(uint16_t bsn) const;
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100260
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100261 void update_rbb(char *rbb);
Daniel Willmannf4a1ec62013-12-28 13:57:31 +0100262 void raise_v_r_to(int moves);
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100263 void raise_v_r(const uint16_t bsn);
264 uint16_t raise_v_q();
Holger Hans Peter Freythercbb00eb2013-11-25 23:26:06 +0100265
Holger Hans Peter Freyther7f3e6622013-11-25 23:51:19 +0100266 void raise_v_q(int);
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100267
Jacob Erlbeckd87e1d62015-12-14 11:43:04 +0100268 void receive_bsn(const uint16_t bsn);
Jacob Erlbeck784a0bd2015-12-14 11:54:29 +0100269 bool invalidate_bsn(const uint16_t bsn);
Daniel Willmann55844792013-12-28 14:41:00 +0100270
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100271 uint16_t m_v_r; /* receive state */
272 uint16_t m_v_q; /* receive window state */
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100273
274 gprs_rlc_v_n m_v_n;
Jacob Erlbecka3a567e2015-12-28 13:46:32 +0100275
276 gprs_rlc_ul_window();
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100277};
278
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200279extern "C" {
280/* TS 04.60 10.2.2 */
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +0100281#if OSMO_IS_LITTLE_ENDIAN
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200282struct rlc_ul_header {
283 uint8_t r:1,
284 si:1,
285 cv:4,
286 pt:2;
287 uint8_t ti:1,
288 tfi:5,
289 pi:1,
290 spare:1;
291 uint8_t e:1,
292 bsn:7;
293} __attribute__ ((packed));
294
295struct rlc_dl_header {
296 uint8_t usf:3,
297 s_p:1,
298 rrbp:2,
299 pt:2;
300 uint8_t fbi:1,
301 tfi:5,
302 pr:2;
303 uint8_t e:1,
304 bsn:7;
305} __attribute__ ((packed));
306
307struct rlc_li_field {
308 uint8_t e:1,
309 m:1,
310 li:6;
311} __attribute__ ((packed));
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100312
313struct rlc_li_field_egprs {
314 uint8_t e:1,
315 li:7;
316} __attribute__ ((packed));
317
Aravind Sirsikar5a5d2b72016-03-16 19:19:17 +0530318/* TS 44.060 10.3a.4.1.1 */
319struct gprs_rlc_ul_header_egprs_1 {
320 uint8_t r:1,
321 si:1,
322 cv:4,
323 tfi_a:2;
324 uint8_t tfi_b:3,
325 bsn1_a:5;
326 uint8_t bsn1_b:6,
327 bsn2_a:2;
328 uint8_t bsn2_b;
329 uint8_t cps:5,
330 rsb:1,
331 pi:1,
332 spare_a:1;
333 uint8_t spare_b:6,
334 dummy:2;
335} __attribute__ ((packed));
336
337/* TS 44.060 10.3a.4.2.1 */
338struct gprs_rlc_ul_header_egprs_2 {
339 uint8_t r:1,
340 si:1,
341 cv:4,
342 tfi_a:2;
343 uint8_t tfi_b:3,
344 bsn1_a:5;
345 uint8_t bsn1_b:6,
346 cps_a:2;
347 uint8_t cps_b:1,
348 rsb:1,
349 pi:1,
350 spare_a:5;
351 uint8_t spare_b:5,
352 dummy:3;
353} __attribute__ ((packed));
354
355/* TS 44.060 10.3a.4.3.1 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100356struct gprs_rlc_ul_header_egprs_3 {
357 uint8_t r:1,
358 si:1,
359 cv:4,
360 tfi_a:2;
361 uint8_t tfi_b:3,
362 bsn1_a:5;
363 uint8_t bsn1_b:6,
364 cps_a:2;
365 uint8_t cps_b:2,
366 spb:2,
367 rsb:1,
368 pi:1,
369 spare:1,
370 dummy:1;
371} __attribute__ ((packed));
Jacob Erlbeckf0e40392016-01-08 10:07:53 +0100372
Jacob Erlbeck9e859392016-02-02 11:48:37 +0100373struct gprs_rlc_dl_header_egprs_1 {
374 uint8_t usf:3,
375 es_p:2,
376 rrbp:2,
377 tfi_a:1;
378 uint8_t tfi_b:4,
379 pr:2,
380 bsn1_a:2;
381 uint8_t bsn1_b:8;
382 uint8_t bsn1_c:1,
383 bsn2_a:7;
384 uint8_t bsn2_b:3,
385 cps:5;
386} __attribute__ ((packed));
387
388struct gprs_rlc_dl_header_egprs_2 {
389 uint8_t usf:3,
390 es_p:2,
391 rrbp:2,
392 tfi_a:1;
393 uint8_t tfi_b:4,
394 pr:2,
395 bsn1_a:2;
396 uint8_t bsn1_b:8;
397 uint8_t bsn1_c:1,
398 cps:3,
399 dummy:4;
400} __attribute__ ((packed));
401
Jacob Erlbeckf0e40392016-01-08 10:07:53 +0100402struct gprs_rlc_dl_header_egprs_3 {
403 uint8_t usf:3,
404 es_p:2,
405 rrbp:2,
406 tfi_a:1;
407 uint8_t tfi_b:4,
408 pr:2,
409 bsn1_a:2;
410 uint8_t bsn1_b:8;
411 uint8_t bsn1_c:1,
412 cps:4,
413 spb:2,
414 dummy:1;
415} __attribute__ ((packed));
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +0100416#else
417# error "Only little endian headers are supported yet. TODO: add missing structs"
418#endif
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200419}
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100420
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100421inline bool gprs_rlc_v_b::is_state(int bsn, const gprs_rlc_dl_bsn_state type) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100422{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100423 return m_v_b[bsn & mod_sns_half()] == type;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100424}
425
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100426inline void gprs_rlc_v_b::mark(int bsn, const gprs_rlc_dl_bsn_state type)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100427{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100428 m_v_b[bsn & mod_sns_half()] = type;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100429}
430
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100431inline bool gprs_rlc_v_b::is_nacked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100432{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100433 return is_state(bsn, GPRS_RLC_DL_BSN_NACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100434}
435
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100436inline bool gprs_rlc_v_b::is_acked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100437{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100438 return is_state(bsn, GPRS_RLC_DL_BSN_ACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100439}
440
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100441inline bool gprs_rlc_v_b::is_unacked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100442{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100443 return is_state(bsn, GPRS_RLC_DL_BSN_UNACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100444}
445
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100446inline bool gprs_rlc_v_b::is_resend(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100447{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100448 return is_state(bsn, GPRS_RLC_DL_BSN_RESEND);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100449}
450
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100451inline bool gprs_rlc_v_b::is_invalid(int bsn) const
Holger Hans Peter Freyther95255672013-11-23 16:18:18 +0100452{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100453 return is_state(bsn, GPRS_RLC_DL_BSN_INVALID);
Holger Hans Peter Freyther95255672013-11-23 16:18:18 +0100454}
455
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100456inline gprs_rlc_dl_bsn_state gprs_rlc_v_b::get_state(int bsn) const
Daniel Willmann146514e2013-12-28 18:24:42 +0100457{
458 return m_v_b[bsn & mod_sns_half()];
459}
460
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100461inline void gprs_rlc_v_b::mark_resend(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100462{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100463 return mark(bsn, GPRS_RLC_DL_BSN_RESEND);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100464}
465
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100466inline void gprs_rlc_v_b::mark_unacked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100467{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100468 return mark(bsn, GPRS_RLC_DL_BSN_UNACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100469}
470
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100471inline void gprs_rlc_v_b::mark_acked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100472{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100473 return mark(bsn, GPRS_RLC_DL_BSN_ACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100474}
475
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100476inline void gprs_rlc_v_b::mark_nacked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100477{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100478 return mark(bsn, GPRS_RLC_DL_BSN_NACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100479}
480
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100481inline void gprs_rlc_v_b::mark_invalid(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100482{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100483 return mark(bsn, GPRS_RLC_DL_BSN_INVALID);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100484}
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100485
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100486inline gprs_rlc_window::gprs_rlc_window()
487 : m_sns(RLC_GPRS_SNS)
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +0100488 , m_ws(RLC_GPRS_WS)
Jacob Erlbecka3a567e2015-12-28 13:46:32 +0100489{
490}
491
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100492inline const uint16_t gprs_rlc_window::sns() const
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100493{
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +0100494 return m_sns;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100495}
496
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100497inline const uint16_t gprs_rlc_window::ws() const
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100498{
Jacob Erlbeck8f8197f2015-12-28 13:51:44 +0100499 return m_ws;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100500}
501
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100502inline const uint16_t gprs_rlc_window::mod_sns() const
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100503{
504 return sns() - 1;
505}
506
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100507inline const uint16_t gprs_rlc_window::mod_sns(uint16_t bsn) const
Jacob Erlbeck93c55d02015-12-23 16:29:07 +0100508{
509 return bsn & mod_sns();
510}
511
Jacob Erlbeckdb883802016-01-19 14:07:33 +0100512inline gprs_rlc_dl_window::gprs_rlc_dl_window()
513 : m_v_s(0)
514 , m_v_a(0)
515{
516}
517
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100518inline const uint16_t gprs_rlc_dl_window::v_s() const
519{
520 return m_v_s;
521}
522
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100523inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const
524{
Jacob Erlbeck93c55d02015-12-23 16:29:07 +0100525 return mod_sns(m_v_s + offset);
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100526}
527
528inline const uint16_t gprs_rlc_dl_window::v_a() const
529{
530 return m_v_a;
531}
532
533inline bool gprs_rlc_dl_window::window_stalled() const
534{
Jacob Erlbeck93c55d02015-12-23 16:29:07 +0100535 return (mod_sns(m_v_s - m_v_a)) == ws();
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100536}
537
538inline bool gprs_rlc_dl_window::window_empty() const
539{
540 return m_v_s == m_v_a;
541}
542
543inline void gprs_rlc_dl_window::increment_send()
544{
545 m_v_s = (m_v_s + 1) & mod_sns();
546}
547
548inline void gprs_rlc_dl_window::raise(int moves)
549{
550 m_v_a = (m_v_a + moves) & mod_sns();
551}
552
553inline const int16_t gprs_rlc_dl_window::distance() const
554{
555 return (m_v_s - m_v_a) & mod_sns();
556}
557
Jacob Erlbecka3a567e2015-12-28 13:46:32 +0100558inline gprs_rlc_ul_window::gprs_rlc_ul_window()
559 : m_v_r(0)
560 , m_v_q(0)
561{
562}
563
Jacob Erlbecke1ca87f2015-12-23 16:40:56 +0100564inline bool gprs_rlc_ul_window::is_in_window(uint16_t bsn) const
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100565{
566 uint16_t offset_v_q;
567
568 /* current block relative to lowest unreceived block */
569 offset_v_q = (bsn - m_v_q) & mod_sns();
570 /* If out of window (may happen if blocks below V(Q) are received
571 * again. */
572 return offset_v_q < ws();
573}
574
Jacob Erlbecke1ca87f2015-12-23 16:40:56 +0100575inline bool gprs_rlc_ul_window::is_received(uint16_t bsn) const
Jacob Erlbeck784a0bd2015-12-14 11:54:29 +0100576{
577 uint16_t offset_v_r;
578
579 /* Offset to the end of the received window */
580 offset_v_r = (m_v_r - 1 - bsn) & mod_sns();
581 return is_in_window(bsn) && m_v_n.is_received(bsn) && offset_v_r < ws();
582}
583
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100584inline const uint16_t gprs_rlc_ul_window::v_r() const
585{
586 return m_v_r;
587}
588
589inline const uint16_t gprs_rlc_ul_window::v_q() const
590{
591 return m_v_q;
592}
593
Daniel Willmann8a31f9e2013-11-27 17:08:35 +0100594inline const uint16_t gprs_rlc_ul_window::ssn() const
595{
596 return m_v_r;
597}
598
Daniel Willmannf4a1ec62013-12-28 13:57:31 +0100599inline void gprs_rlc_ul_window::raise_v_r_to(int moves)
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100600{
Jacob Erlbeck93c55d02015-12-23 16:29:07 +0100601 m_v_r = mod_sns(m_v_r + moves);
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100602}
603
Holger Hans Peter Freyther7f3e6622013-11-25 23:51:19 +0100604inline void gprs_rlc_ul_window::raise_v_q(int incr)
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100605{
Jacob Erlbeck93c55d02015-12-23 16:29:07 +0100606 m_v_q = mod_sns(m_v_q + incr);
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100607}
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100608
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100609inline void gprs_rlc_v_n::mark_received(int bsn)
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100610{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100611 return mark(bsn, GPRS_RLC_UL_BSN_RECEIVED);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100612}
613
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100614inline void gprs_rlc_v_n::mark_missing(int bsn)
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100615{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100616 return mark(bsn, GPRS_RLC_UL_BSN_MISSING);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100617}
618
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100619inline bool gprs_rlc_v_n::is_received(int bsn) const
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100620{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100621 return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100622}
623
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100624inline bool gprs_rlc_v_n::is_state(int bsn, gprs_rlc_ul_bsn_state type) const
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100625{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100626 return m_v_n[bsn & mod_sns_half()] == type;
627}
628
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100629inline void gprs_rlc_v_n::mark(int bsn, gprs_rlc_ul_bsn_state type)
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100630{
631 m_v_n[bsn & mod_sns_half()] = type;
632}
633
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100634inline gprs_rlc_ul_bsn_state gprs_rlc_v_n::state(int bsn) const
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100635{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100636 return m_v_n[bsn & mod_sns_half()];
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100637}
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100638
639inline gprs_rlc_data *gprs_rlc::block(int bsn)
640{
641 return &m_blocks[bsn & mod_sns_half()];
642}