aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-08-17 13:13:27 +0200
committerHarald Welte <laforge@gnumonks.org>2018-08-17 14:13:47 +0000
commit82f13612ce63b863d22bc28eaf3dcc25c364fb6c (patch)
treeb7aa36532abc0758928ec6b637b479a4e3f54c48
parent67f1d1edf49258f37b021357b00c25c79d973ae8 (diff)
gbproxy: Add new VTY-managed timer: link-list clean-stale-timer
This timer allows periodically cleaning up stale links in link-list of each gbproxy_peer. Previous to this patch, this kind of cleanup (gbproxy_remove_stale_link_infos) was being done only as a consequence of external events being triggered, such as a message from that peer being received. It was found in a production network agreggating several BSS that some of them were offline for a longtime but gbproxy was still caching big amounts of really old link_info for the NSEI assigned to those BSS, because since they were probably turned off abruptely, no new messages were received from it which would trigger the cleanup. As a consequence, it has been observed that a timer to periodically clean up old entries (link-list max-age) is requird in case w don't receive messages from that NSEI periodically. Related: SYS#4431 Change-Id: Ic777016f6d4f0e30fb736484774ca46878f17b7a
-rw-r--r--include/osmocom/sgsn/gb_proxy.h5
-rw-r--r--src/gprs/gb_proxy_peer.c21
-rw-r--r--src/gprs/gb_proxy_vty.c43
3 files changed, 67 insertions, 2 deletions
diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h
index 16082fcde..7e2ae42fb 100644
--- a/include/osmocom/sgsn/gb_proxy.h
+++ b/include/osmocom/sgsn/gb_proxy.h
@@ -105,6 +105,8 @@ struct gbproxy_config {
struct osmo_plmn_id core_plmn;
uint8_t* core_apn;
size_t core_apn_size;
+ /* Frequency (sec) at which timer to clean stale links is fired (0 disabled) */
+ unsigned int clean_stale_timer_freq;
/* 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) */
@@ -151,6 +153,9 @@ struct gbproxy_peer {
struct rate_ctr_group *ctrg;
struct gbproxy_patch_state patch_state;
+
+ /* Fired periodically to clean up stale links from list */
+ struct osmo_timer_list clean_stale_timer;
};
struct gbproxy_tlli_state {
diff --git a/src/gprs/gb_proxy_peer.c b/src/gprs/gb_proxy_peer.c
index f2cdd9388..8e28fc4bc 100644
--- a/src/gprs/gb_proxy_peer.c
+++ b/src/gprs/gb_proxy_peer.c
@@ -167,6 +167,19 @@ struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(struct gbproxy_config *cfg,
return NULL;
}
+static void clean_stale_timer_cb(void *data)
+{
+ time_t now;
+ struct timespec ts = {0,};
+ struct gbproxy_peer *peer = (struct gbproxy_peer *) data;
+
+ osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
+ now = ts.tv_sec;
+ gbproxy_remove_stale_link_infos(peer, now);
+ if (peer->cfg->clean_stale_timer_freq != 0)
+ osmo_timer_schedule(&peer->clean_stale_timer,
+ peer->cfg->clean_stale_timer_freq, 0);
+}
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)
{
@@ -188,13 +201,18 @@ struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvc
INIT_LLIST_HEAD(&peer->patch_state.logical_links);
+ osmo_timer_setup(&peer->clean_stale_timer, clean_stale_timer_cb, peer);
+ if (peer->cfg->clean_stale_timer_freq != 0)
+ osmo_timer_schedule(&peer->clean_stale_timer,
+ peer->cfg->clean_stale_timer_freq, 0);
+
return peer;
}
void gbproxy_peer_free(struct gbproxy_peer *peer)
{
llist_del(&peer->list);
-
+ osmo_timer_del(&peer->clean_stale_timer);
gbproxy_delete_link_infos(peer);
rate_ctr_group_free(peer->ctrg);
@@ -220,4 +238,3 @@ int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bv
return counter;
}
-
diff --git a/src/gprs/gb_proxy_vty.c b/src/gprs/gb_proxy_vty.c
index d74335556..52c39fdcd 100644
--- a/src/gprs/gb_proxy_vty.c
+++ b/src/gprs/gb_proxy_vty.c
@@ -120,6 +120,9 @@ static int config_write_gbproxy(struct vty *vty)
vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
VTY_NEWLINE);
+ if (g_cfg->clean_stale_timer_freq > 0)
+ vty_out(vty, " link-list clean-stale-timer %u%s",
+ g_cfg->clean_stale_timer_freq, VTY_NEWLINE);
if (g_cfg->tlli_max_age > 0)
vty_out(vty, " link-list max-age %d%s",
g_cfg->tlli_max_age, VTY_NEWLINE);
@@ -407,6 +410,44 @@ 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_CLEAN_STALE_TIMER_STR "Periodic timer to clean stale links\n"
+
+DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
+ cfg_gbproxy_link_list_clean_stale_timer_cmd,
+ "link-list clean-stale-timer <1-999999>",
+ GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR
+ "Frequency at which the periodic timer is fired (in seconds)\n")
+{
+ struct gbproxy_peer *peer;
+ g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
+
+ /* Re-schedule running timers soon in case prev frequency was really big
+ and new frequency is desired to be lower. After initial run, periodic
+ time is used. Use random() to avoid firing timers for all peers at
+ the same time */
+ llist_for_each_entry(peer, &g_cfg->bts_peers, list)
+ osmo_timer_schedule(&peer->clean_stale_timer,
+ random() % 5, random() % 1000000);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
+ cfg_gbproxy_link_list_no_clean_stale_timer_cmd,
+ "no link-list clean-stale-timer",
+ NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)
+
+{
+ struct gbproxy_peer *peer;
+ g_cfg->clean_stale_timer_freq = 0;
+
+ llist_for_each_entry(peer, &g_cfg->bts_peers, list)
+ osmo_timer_del(&peer->clean_stale_timer);
+
+ return CMD_SUCCESS;
+}
+
#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
DEFUN(cfg_gbproxy_link_list_max_age,
@@ -846,6 +887,7 @@ int gbproxy_vty_init(void)
install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_clean_stale_timer_cmd);
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);
@@ -857,6 +899,7 @@ int gbproxy_vty_init(void)
install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_clean_stale_timer_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);