blob: fe14c6aae3d441047ef73acf2de70d4c06980678 [file] [log] [blame]
Pau Espin Pedrol5c598c72022-03-31 20:22:05 +02001/* 3GPP TS 44.064
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +01002 * Copyright (C) 2013 by Holger Hans Peter Freyther
Pau Espin Pedrol4f8384b2022-03-31 19:36:12 +02003 * Copyright (C) 2022 by by Sysmocom s.f.m.c. GmbH
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +01004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010014 */
15
16#pragma once
17
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010018#ifdef __cplusplus
Jacob Erlbeck1eae96c2015-06-15 11:19:13 +020019extern "C" {
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010020#endif
Jacob Erlbeck1eae96c2015-06-15 11:19:13 +020021
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010022#include <stdint.h>
Holger Hans Peter Freytheracb54272013-11-07 08:15:58 +010023#include <string.h>
Pau Espin Pedrol1de68732020-03-11 14:04:52 +010024#include <time.h>
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010025
Pau Espin Pedrol5c598c72022-03-31 20:22:05 +020026#include <osmocom/core/endian.h>
Pau Espin Pedrol4f8384b2022-03-31 19:36:12 +020027#include <osmocom/core/linuxlist.h>
28#include <osmocom/core/msgb.h>
Pau Espin Pedrol5c598c72022-03-31 20:22:05 +020029#include <osmocom/core/endian.h>
Pau Espin Pedrol4f8384b2022-03-31 19:36:12 +020030
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +020031#include "gprs_codel.h"
32
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010033#define LLC_MAX_LEN 1543
34
Pau Espin Pedrol2182e622021-01-14 16:48:38 +010035struct gprs_rlcmac_bts;
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +020036struct GprsMs;
Jacob Erlbeck1d0a52a2015-06-02 11:28:07 +020037
Pau Espin Pedrol5c598c72022-03-31 20:22:05 +020038struct gprs_llc_hdr {
39#if OSMO_IS_LITTLE_ENDIAN
40 union { /* 5.2, 6.2.0 */
41 uint8_t address;
42 uint8_t sapi:4, unused:2, c_r:1, pd:1;
43#elif OSMO_IS_BIG_ENDIAN
44/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
45 union {
46 uint8_t address;
47 uint8_t pd:1, c_r:1, unused:2, sapi:4;
48#endif
49 };
50 uint8_t control[0];
51} __attribute__ ((packed));
52
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010053/**
54 * I represent the LLC data to a MS
55 */
56struct gprs_llc {
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010057 uint8_t frame[LLC_MAX_LEN]; /* current DL or UL frame */
Pau Espin Pedrol14633832022-03-31 19:08:07 +020058 uint16_t index; /* current write/read position of frame */
59 uint16_t length; /* len of current DL LLC_frame, 0 == no frame */
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +020060};
Pau Espin Pedrol4f8384b2022-03-31 19:36:12 +020061bool llc_is_user_data_frame(const uint8_t *data, size_t len);
62
63void llc_init(struct gprs_llc *llc);
64void llc_reset(struct gprs_llc *llc);
65void llc_reset_frame_space(struct gprs_llc *llc);
66
67void llc_put_frame(struct gprs_llc *llc, const uint8_t *data, size_t len);
68void llc_put_dummy_frame(struct gprs_llc *llc, size_t req_len);
69void llc_append_frame(struct gprs_llc *llc, const uint8_t *data, size_t len);
Holger Hans Peter Freyther550bb882013-12-04 17:10:54 +010070
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010071static inline uint16_t llc_chunk_size(const struct gprs_llc *llc)
Holger Hans Peter Freytheracb54272013-11-07 08:15:58 +010072{
Pau Espin Pedrol14633832022-03-31 19:08:07 +020073 return llc->length - llc->index;
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010074}
75
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010076static inline uint16_t llc_remaining_space(const struct gprs_llc *llc)
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010077{
Pau Espin Pedrol14633832022-03-31 19:08:07 +020078 return LLC_MAX_LEN - llc->length;
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010079}
80
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010081static inline uint16_t llc_frame_length(const struct gprs_llc *llc)
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010082{
Pau Espin Pedrol14633832022-03-31 19:08:07 +020083 return llc->length;
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010084}
85
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010086static inline void llc_consume(struct gprs_llc *llc, size_t len)
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010087{
Pau Espin Pedrol14633832022-03-31 19:08:07 +020088 llc->index += len;
Holger Hans Peter Freytheracb54272013-11-07 08:15:58 +010089}
90
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010091static inline void llc_consume_data(struct gprs_llc *llc, uint8_t *data, size_t len)
Holger Hans Peter Freytheracb54272013-11-07 08:15:58 +010092{
93 /* copy and increment index */
Pau Espin Pedrol14633832022-03-31 19:08:07 +020094 memcpy(data, llc->frame + llc->index, len);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010095 llc_consume(llc, len);
Holger Hans Peter Freytheracb54272013-11-07 08:15:58 +010096}
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010097
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010098static inline bool llc_fits_in_current_frame(const struct gprs_llc *llc, uint8_t chunk_size)
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +010099{
Pau Espin Pedrol14633832022-03-31 19:08:07 +0200100 return llc->length + chunk_size <= LLC_MAX_LEN;
Holger Hans Peter Freythere2310262013-11-13 16:56:15 +0100101}
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200102
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200103struct MetaInfo {
104 struct timespec recv_time;
105 struct timespec expire_time;
106};
107/**
108 * I store the LLC frames that come from the SGSN.
109 */
Pau Espin Pedrol5c598c72022-03-31 20:22:05 +0200110enum gprs_llc_queue_prio { /* lowest value has highest prio */
111 LLC_QUEUE_PRIO_GMM = 0, /* SAPI 1 */
112 LLC_QUEUE_PRIO_TOM_SMS, /* SAPI 2,7,8 */
113 LLC_QUEUE_PRIO_OTHER, /* Other SAPIs */
114 _LLC_QUEUE_PRIO_SIZE /* used to calculate size of enum */
115};
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +0200116struct gprs_llc_prio_queue {
117 struct gprs_codel codel_state;
118 struct llist_head queue; /* queued LLC DL data. See enum gprs_llc_queue_prio. */
119};
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200120struct gprs_llc_queue {
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +0200121 struct GprsMs *ms; /* backpointer */
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200122 uint32_t avg_queue_delay; /* Average delay of data going through the queue */
123 size_t queue_size;
124 size_t queue_octets;
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +0200125 bool use_codel;
126 struct gprs_llc_prio_queue pq[_LLC_QUEUE_PRIO_SIZE]; /* queued LLC DL data. See enum gprs_llc_queue_prio. */
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200127};
128
129void llc_queue_calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec,
130 struct timespec *tv);
131bool llc_queue_is_frame_expired(const struct timespec *tv_now, const struct timespec *tv);
132
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +0200133void llc_queue_init(struct gprs_llc_queue *q, struct GprsMs *ms);
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200134void llc_queue_clear(struct gprs_llc_queue *q, struct gprs_rlcmac_bts *bts);
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +0200135void llc_queue_set_codel_interval(struct gprs_llc_queue *q, unsigned int interval);
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200136void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o);
137void llc_queue_enqueue(struct gprs_llc_queue *q, struct msgb *llc_msg, const struct timespec *expire_time);
Pau Espin Pedrol6b1e9512022-04-04 13:45:56 +0200138struct msgb *llc_queue_dequeue(struct gprs_llc_queue *q);
Pau Espin Pedrolee1cb752022-03-31 19:47:33 +0200139
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100140static inline size_t llc_queue_size(const struct gprs_llc_queue *q)
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200141{
Pau Espin Pedrol14633832022-03-31 19:08:07 +0200142 return q->queue_size;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200143}
Jacob Erlbeck07eb6552015-06-15 11:05:44 +0200144
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100145static inline size_t llc_queue_octets(const struct gprs_llc_queue *q)
Jacob Erlbeck07eb6552015-06-15 11:05:44 +0200146{
Pau Espin Pedrol14633832022-03-31 19:08:07 +0200147 return q->queue_octets;
Jacob Erlbeck07eb6552015-06-15 11:05:44 +0200148}
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100149
150#ifdef __cplusplus
151}
152#endif