osmo-pcu/src/gprs_ms.h

254 lines
6.7 KiB
C
Raw Normal View History

/* gprs_ms.h
*
* Copyright (C) 2015-2020 by Sysmocom s.f.m.c. GmbH
* Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#pragma once
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
2015-07-17 14:39:09 +00:00
struct gprs_codel;
#include "llc.h"
#include "tbf.h"
#include "tbf_ul.h"
#include "tbf_dl.h"
#include "pcu_l1_if.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <osmocom/core/timer.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm48.h>
#include "coding_scheme.h"
#include <gsm_rlcmac.h>
#include <stdint.h>
#include <stddef.h>
#include <inttypes.h>
enum ms_counter_id {
MS_CTR_DL_CTRL_MSG_SCHED,
};
struct gprs_rlcmac_bts;
struct gprs_rlcmac_trx;
struct GprsMs;
struct gpr_ms_callback {
void (*ms_idle)(struct GprsMs *);
void (*ms_active)(struct GprsMs *);
};
struct GprsMs {
struct llist_head list; /* list of all GprsMs */
struct gpr_ms_callback cb;
bool app_info_pending;
struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_dl_tbf *dl_tbf;
struct llist_head old_tbfs; /* list of gprs_rlcmac_tbf */
uint32_t tlli;
uint32_t new_ul_tlli;
uint32_t new_dl_tlli;
/* store IMSI for look-up and PCH retransmission */
char imsi[OSMO_IMSI_BUF_SIZE];
uint8_t ta;
uint8_t ms_class;
uint8_t egprs_ms_class;
/* current coding scheme */
enum CodingScheme current_cs_ul;
enum CodingScheme current_cs_dl;
struct gprs_llc_queue llc_queue;
bool is_idle;
int ref;
struct osmo_timer_list timer;
unsigned delay;
int64_t last_cs_not_low;
struct pcu_l1_meas l1_meas;
unsigned nack_rate_dl;
uint8_t reserved_dl_slots;
uint8_t reserved_ul_slots;
struct gprs_rlcmac_trx *current_trx;
struct gprs_codel *codel_state;
enum mcs_kind mode;
struct rate_ctr_group *ctrs;
struct nacc_fsm_ctx *nacc;
};
struct GprsMs *ms_alloc(struct gprs_rlcmac_bts *bts, uint32_t tlli);
int ms_first_common_ts(const struct GprsMs *ms);
void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx,
uint8_t ul_slots, uint8_t dl_slots);
struct GprsMs *ms_ref(struct GprsMs *ms);
void ms_unref(struct GprsMs *ms);
void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode);
void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_);
void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_);
void ms_set_ta(struct GprsMs *ms, uint8_t ta_);
enum CodingScheme ms_current_cs_dl(const struct GprsMs *ms, enum mcs_kind req_mcs_kind);
enum CodingScheme ms_max_cs_ul(const struct GprsMs *ms);
enum CodingScheme ms_max_cs_dl(const struct GprsMs *ms);
void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme);
void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate);
uint8_t ms_current_pacch_slots(const struct GprsMs *ms);
void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms);
void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf);
void ms_detach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf);
void ms_set_tlli(struct GprsMs *ms, uint32_t tlli);
bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli);
void ms_set_imsi(struct GprsMs *ms, const char *imsi);
void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas);
struct gprs_rlcmac_tbf *ms_tbf(const struct GprsMs *ms, enum gprs_rlcmac_tbf_direction dir);
static inline struct gprs_rlcmac_ul_tbf *ms_ul_tbf(const struct GprsMs *ms) {return ms->ul_tbf;}
static inline struct gprs_rlcmac_dl_tbf *ms_dl_tbf(const struct GprsMs *ms) {return ms->dl_tbf;}
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
2015-07-17 14:39:09 +00:00
void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb);
int ms_nacc_start(struct GprsMs *ms, Packet_Cell_Change_Notification_t *notif);
bool ms_nacc_rts(const struct GprsMs *ms);
struct msgb *ms_nacc_create_rlcmac_msg(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts);
static inline bool ms_is_idle(const struct GprsMs *ms)
{
return !ms->ul_tbf && !ms->dl_tbf && !ms->ref && llist_empty(&ms->old_tbfs);
}
static inline struct gprs_llc_queue *ms_llc_queue(struct GprsMs *ms)
{
return &ms->llc_queue;
}
static inline bool ms_need_dl_tbf(struct GprsMs *ms)
{
if (ms_dl_tbf(ms) != NULL &&
tbf_state((const struct gprs_rlcmac_tbf *)ms_dl_tbf(ms)) != TBF_ST_WAIT_RELEASE)
return false;
return llc_queue_size(ms_llc_queue(ms)) > 0;
}
static inline uint32_t ms_tlli(const struct GprsMs *ms)
{
if (ms->new_ul_tlli != GSM_RESERVED_TMSI)
return ms->new_ul_tlli;
if (ms->tlli != GSM_RESERVED_TMSI)
return ms->tlli;
return ms->new_dl_tlli;
}
static inline bool ms_check_tlli(struct GprsMs *ms, uint32_t tlli)
{
return tlli != GSM_RESERVED_TMSI &&
(tlli == ms->tlli || tlli == ms->new_ul_tlli || tlli == ms->new_dl_tlli);
}
static inline const char *ms_imsi(const struct GprsMs *ms)
{
return ms->imsi;
}
static inline uint8_t ms_ta(const struct GprsMs *ms)
{
return ms->ta;
}
static inline uint8_t ms_ms_class(const struct GprsMs *ms)
{
return ms->ms_class;
}
static inline uint8_t ms_egprs_ms_class(const struct GprsMs *ms)
{
return ms->egprs_ms_class;
}
static inline enum CodingScheme ms_current_cs_ul(const struct GprsMs *ms)
{
return ms->current_cs_ul;
}
static inline enum mcs_kind ms_mode(const struct GprsMs *ms)
{
return ms->mode;
}
static inline void ms_set_timeout(struct GprsMs *ms, unsigned secs)
{
ms->delay = secs;
}
static inline struct gprs_codel *ms_codel_state(const struct GprsMs *ms)
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
2015-07-17 14:39:09 +00:00
{
return ms->codel_state;
llc: Use CoDel to drop packages from the LLC queue Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
2015-07-17 14:39:09 +00:00
}
static inline unsigned ms_nack_rate_dl(const struct GprsMs *ms)
{
return ms->nack_rate_dl;
}
static inline uint8_t ms_reserved_dl_slots(const struct GprsMs *ms)
{
return ms->reserved_dl_slots;
}
static inline uint8_t ms_reserved_ul_slots(const struct GprsMs *ms)
{
return ms->reserved_ul_slots;
}
static inline struct gprs_rlcmac_trx *ms_current_trx(const struct GprsMs *ms)
{
return ms->current_trx;
}
#define LOGPMS(ms, category, level, fmt, args...) \
LOGP(category, level, "MS(TLLI=0x%08x, IMSI=%s, TA=%" PRIu8 ", %" PRIu8 "/%" PRIu8 ",%s%s) " fmt, \
ms_tlli(ms), ms_imsi(ms), ms_ta(ms), ms_ms_class(ms), ms_egprs_ms_class(ms), \
ms_ul_tbf(ms) ? " UL": "", \
ms_dl_tbf(ms) ? " DL": "", \
## args)
#ifdef __cplusplus
}
#endif