aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-08-16 12:11:46 +0200
committerHarald Welte <laforge@gnumonks.org>2018-08-17 14:13:24 +0000
commit67f1d1edf49258f37b021357b00c25c79d973ae8 (patch)
treee5eeb04591705b209af4a5dcb0e93144187f8e01
parent36abeadc7ba6ff15a3e01230195309f87f788f33 (diff)
gbproxy: Add VTY parameter: link stored-msgs-max-length
It was discovered in some prod setups that some TLLIs can maintain quite long queues of msgb in case its IMSI is not acquired and the tlli is not pruned due to link-list max-{age,length} being set to 0. As a result, the osmo-gpbroxy steadly increases the list size of maintained TLLIs, and some TLLI was found without IMSI catching already 1211 msgb. Let's allow setting a maxiumum length for the queue storing those msgb in a per TLLI base. If the limit is reached, oldest msgb are removed before adding a new one. Depends: libosmocore Change-Id I33b501e89a8f29e4aa121696bcbb13d4b83db40f Related: SYS#4297 Change-Id: I4473be8604f80302df03ffdd5a13280dc072f824
-rw-r--r--include/osmocom/sgsn/gb_proxy.h5
-rw-r--r--src/gprs/gb_proxy.c24
-rw-r--r--src/gprs/gb_proxy_vty.c38
3 files changed, 59 insertions, 8 deletions
diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h
index 70de3d7..16082fc 100644
--- a/include/osmocom/sgsn/gb_proxy.h
+++ b/include/osmocom/sgsn/gb_proxy.h
@@ -105,8 +105,12 @@ struct gbproxy_config {
struct osmo_plmn_id core_plmn;
uint8_t* core_apn;
size_t core_apn_size;
+ /* If !0, Max age to consider a struct gbproxy_link_info as stale */
int tlli_max_age;
+ /* If !0, Max len of gbproxy_peer->list (list of struct gbproxy_link_info) */
int tlli_max_len;
+ /* If !0, Max len of gbproxy_link_info->stored_msgs (list of msgb) */
+ uint32_t stored_msgs_max_len;
/* Experimental config */
int patch_ptmsi;
@@ -171,6 +175,7 @@ struct gbproxy_link_info {
int imsi_acq_pending;
struct llist_head stored_msgs;
+ uint32_t stored_msgs_len;
unsigned vu_gen_tx_bss;
int is_deregistered;
diff --git a/src/gprs/gb_proxy.c b/src/gprs/gb_proxy.c
index f834ed3..8bb6789 100644
--- a/src/gprs/gb_proxy.c
+++ b/src/gprs/gb_proxy.c
@@ -338,7 +338,8 @@ static int gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
msgb_nsei(msg));
/* Patch and flush stored messages towards the SGSN */
- while ((stored_msg = msgb_dequeue(&link_info->stored_msgs))) {
+ while ((stored_msg = msgb_dequeue_count(&link_info->stored_msgs,
+ &link_info->stored_msgs_len))) {
struct gprs_gb_parse_context tmp_parse_ctx = {0};
tmp_parse_ctx.to_bss = 0;
tmp_parse_ctx.peer_nsei = msgb_nsei(stored_msg);
@@ -492,6 +493,24 @@ static int gbproxy_imsi_acquisition(struct gbproxy_peer *peer,
/* The message cannot be processed since the IMSI is still missing */
+ /* If queue is getting too large, drop oldest msgb before adding new one */
+ if (peer->cfg->stored_msgs_max_len > 0) {
+ int exceeded_max_len = link_info->stored_msgs_len
+ + 1 - peer->cfg->stored_msgs_max_len;
+
+ for (; exceeded_max_len > 0; exceeded_max_len--) {
+ struct msgb *msgb_drop;
+ msgb_drop = msgb_dequeue_count(&link_info->stored_msgs,
+ &link_info->stored_msgs_len);
+ LOGP(DLLC, LOGL_INFO,
+ "NSEI=%d(BSS) Dropping stored msgb from list "
+ "(!acq imsi, length %d, max_len exceeded)\n",
+ msgb_nsei(msgb_drop), link_info->stored_msgs_len);
+
+ msgb_free(msgb_drop);
+ }
+ }
+
/* Enqueue unpatched messages */
LOGP(DLLC, LOGL_INFO,
"NSEI=%d(BSS) IMSI acquisition in progress, "
@@ -500,7 +519,8 @@ static int gbproxy_imsi_acquisition(struct gbproxy_peer *peer,
parse_ctx->llc_msg_name ? parse_ctx->llc_msg_name : "BSSGP");
stored_msg = bssgp_msgb_copy(msg, "process_bssgp_ul");
- msgb_enqueue(&link_info->stored_msgs, stored_msg);
+ msgb_enqueue_count(&link_info->stored_msgs, stored_msg,
+ &link_info->stored_msgs_len);
if (!link_info->imsi_acq_pending) {
LOGP(DLLC, LOGL_INFO,
diff --git a/src/gprs/gb_proxy_vty.c b/src/gprs/gb_proxy_vty.c
index cd10abf..d743355 100644
--- a/src/gprs/gb_proxy_vty.c
+++ b/src/gprs/gb_proxy_vty.c
@@ -23,6 +23,7 @@
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
+#include <inttypes.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/rate_ctr.h>
@@ -128,6 +129,9 @@ static int config_write_gbproxy(struct vty *vty)
vty_out(vty, " link-list keep-mode %s%s",
get_value_string(keep_modes, g_cfg->keep_link_infos),
VTY_NEWLINE);
+ if (g_cfg->stored_msgs_max_len > 0)
+ vty_out(vty, " link stored-msgs-max-length %"PRIu32"%s",
+ g_cfg->stored_msgs_max_len, VTY_NEWLINE);
return CMD_SUCCESS;
@@ -402,6 +406,7 @@ DEFUN(cfg_gbproxy_no_secondary_sgsn,
}
#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
+#define GBPROXY_LINK_STR "Set TLLI parameters\n"
#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
DEFUN(cfg_gbproxy_link_list_max_age,
@@ -464,6 +469,27 @@ DEFUN(cfg_gbproxy_link_list_keep_mode,
return CMD_SUCCESS;
}
+DEFUN(cfg_gbproxy_link_stored_msgs_max_len,
+ cfg_gbproxy_link_stored_msgs_max_len_cmd,
+ "link stored-msgs-max-length <1-99999>",
+ GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR
+ "Maximum number of msgb stored in the logical link waiting to acquire its IMSI\n")
+{
+ g_cfg->stored_msgs_max_len = (uint32_t) atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_gbproxy_link_no_stored_msgs_max_len,
+ cfg_gbproxy_link_no_stored_msgs_max_len_cmd,
+ "no link stored-msgs-max-length",
+ NO_STR GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR)
+{
+ g_cfg->stored_msgs_max_len = 0;
+
+ return CMD_SUCCESS;
+}
+
DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
@@ -502,10 +528,6 @@ DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
llist_for_each_entry(link_info, &state->logical_links, list) {
time_t age = now - link_info->timestamp;
- int stored_msgs = 0;
- struct llist_head *iter;
- llist_for_each(iter, &link_info->stored_msgs)
- stored_msgs++;
if (link_info->imsi > 0) {
snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
@@ -518,8 +540,10 @@ DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
link_info->tlli.current, mi_buf, (int)age);
- if (stored_msgs)
- vty_out(vty, ", STORED %d", stored_msgs);
+ if (link_info->stored_msgs_len)
+ vty_out(vty, ", STORED %"PRIu32"/%"PRIu32,
+ link_info->stored_msgs_len,
+ g_cfg->stored_msgs_max_len);
if (g_cfg->route_to_sgsn2)
vty_out(vty, ", SGSN NSEI %d",
@@ -825,6 +849,7 @@ int gbproxy_vty_init(void)
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_link_stored_msgs_max_len_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
@@ -834,6 +859,7 @@ int gbproxy_vty_init(void)
install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_link_no_stored_msgs_max_len_cmd);
/* broken or deprecated to allow an upgrade path */
install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);