aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-12-19 19:18:54 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-01-18 18:11:08 +0100
commit03b463034885e7ebb09160f6d63c05ac120a8098 (patch)
treef04b6e49fc98b07c9f62993ce3a5f5c5ad202c99
parente154d8bdd45974fa6e9408b9d543eb9e9ea94b79 (diff)
gprs: Send PING and eventually reconnect
Currently, the reconnect mechanism relies on gsup_client_updown_cb which in turn gets called based on the OS' view of connection state. This patch adds a timer based PING mechanism that regularly sends PING messages and forces a reconnect if a PONG message won't be received until the next PING message is scheduled. The current ping interval is 20s. Sponsored-by: On-Waves ehf Conflicts: openbsc/src/gprs/gprs_gsup_client.c [hfreyther: Conflicts due the potential memleak fix by me. Removed another TODO from the code as we stop the ping/pong timer]
-rw-r--r--openbsc/include/openbsc/gprs_gsup_client.h3
-rw-r--r--openbsc/src/gprs/gprs_gsup_client.c61
2 files changed, 61 insertions, 3 deletions
diff --git a/openbsc/include/openbsc/gprs_gsup_client.h b/openbsc/include/openbsc/gprs_gsup_client.h
index 1165c4a78..9537db4c7 100644
--- a/openbsc/include/openbsc/gprs_gsup_client.h
+++ b/openbsc/include/openbsc/gprs_gsup_client.h
@@ -24,6 +24,7 @@
#include <osmocom/core/timer.h>
#define GPRS_GSUP_RECONNECT_INTERVAL 10
+#define GPRS_GSUP_PING_INTERVAL 20
struct msgb;
struct ipa_client_conn;
@@ -37,8 +38,10 @@ struct gprs_gsup_client {
gprs_gsup_read_cb_t read_cb;
void *data;
+ struct osmo_timer_list ping_timer;
struct osmo_timer_list connect_timer;
int is_connected;
+ int got_ipa_pong;
};
struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr,
diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c
index 986542953..523c541b7 100644
--- a/openbsc/src/gprs/gprs_gsup_client.c
+++ b/openbsc/src/gprs/gprs_gsup_client.c
@@ -33,6 +33,18 @@
extern void *tall_bsc_ctx;
+static void start_test_procedure(struct gprs_gsup_client *gsupc);
+
+static void gsup_client_send_ping(struct gprs_gsup_client *gsupc)
+{
+ struct msgb *msg = gprs_gsup_msgb_alloc();
+
+ msg->l2h = msgb_put(msg, 1);
+ msg->l2h[0] = IPAC_MSGT_PING;
+ ipa_msg_push_header(msg, IPAC_PROTO_IPACCESS);
+ ipa_client_conn_send(gsupc->link, msg);
+}
+
static int gsup_client_connect(struct gprs_gsup_client *gsupc)
{
int rc;
@@ -46,6 +58,12 @@ static int gsup_client_connect(struct gprs_gsup_client *gsupc)
osmo_timer_del(&gsupc->connect_timer);
}
+ if (osmo_timer_pending(&gsupc->ping_timer)) {
+ LOGP(DLINP, LOGL_DEBUG,
+ "GSUP connect: ping timer already running\n");
+ osmo_timer_del(&gsupc->ping_timer);
+ }
+
if (ipa_client_conn_clear_queue(gsupc->link) > 0)
LOGP(DLINP, LOGL_DEBUG, "GSUP connect: discarded stored messages\n");
@@ -83,17 +101,17 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up)
{
struct gprs_gsup_client *gsupc = link->data;
- LOGP(DGPRS, LOGL_NOTICE, "GSUP link to %s:%d %s\n",
+ LOGP(DGPRS, LOGL_INFO, "GSUP link to %s:%d %s\n",
link->addr, link->port, up ? "UP" : "DOWN");
gsupc->is_connected = up;
if (up) {
- /* TODO: Start ping procedure */
+ start_test_procedure(gsupc);
osmo_timer_del(&gsupc->connect_timer);
} else {
- /* TODO: Stop ping procedure */
+ osmo_timer_del(&gsupc->ping_timer);
osmo_timer_schedule(&gsupc->connect_timer,
GPRS_GSUP_RECONNECT_INTERVAL, 0);
@@ -125,7 +143,12 @@ static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg)
}
if (rc == 1) {
+ uint8_t msg_type = *(msg->l2h);
/* CCM message */
+ if (msg_type == IPAC_MSGT_PONG) {
+ LOGP(DGPRS, LOGL_DEBUG, "GSUP receiving PONG\n");
+ gsupc->got_ipa_pong = 1;
+ }
msgb_free(msg);
return 0;
@@ -155,6 +178,37 @@ invalid:
return -1;
}
+static void ping_timer_cb(void *gsupc_)
+{
+ struct gprs_gsup_client *gsupc = gsupc_;
+
+ LOGP(DGPRS, LOGL_INFO, "GSUP ping callback (%s, %s PONG)\n",
+ gsupc->is_connected ? "connected" : "not connected",
+ gsupc->got_ipa_pong ? "got" : "didn't get");
+
+ if (gsupc->got_ipa_pong) {
+ start_test_procedure(gsupc);
+ return;
+ }
+
+ LOGP(DGPRS, LOGL_NOTICE, "GSUP ping timed out, reconnecting\n");
+ ipa_client_conn_close(gsupc->link);
+ gsupc->is_connected = 0;
+
+ gsup_client_connect(gsupc);
+}
+
+static void start_test_procedure(struct gprs_gsup_client *gsupc)
+{
+ gsupc->ping_timer.data = gsupc;
+ gsupc->ping_timer.cb = &ping_timer_cb;
+
+ gsupc->got_ipa_pong = 0;
+ osmo_timer_schedule(&gsupc->ping_timer, GPRS_GSUP_PING_INTERVAL, 0);
+ LOGP(DGPRS, LOGL_DEBUG, "GSUP sending PING\n");
+ gsup_client_send_ping(gsupc);
+}
+
struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr,
unsigned int tcp_port,
gprs_gsup_read_cb_t read_cb)
@@ -196,6 +250,7 @@ failed:
void gprs_gsup_client_destroy(struct gprs_gsup_client *gsupc)
{
osmo_timer_del(&gsupc->connect_timer);
+ osmo_timer_del(&gsupc->ping_timer);
if (gsupc->link) {
ipa_client_conn_close(gsupc->link);