aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-05-03 11:51:07 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-05-03 11:51:07 +0800
commit45403b1804d2318aec2858c28ac4c623bfdcde2f (patch)
tree772fb64f3adfd8028c7d63df19f91c6fdd0055ab
parent6782cea4bf33f4142fd4aa65467149a34c35725a (diff)
nat/bsc: Send PONG on PING, send PING from the BSC too
We do want to send PING/PONG in both ways to have a heartbeat on the TCP connection. When switching over to SCTP we can rely on the builtin heartbeat functionality.
-rw-r--r--openbsc/src/bsc_msc_ip.c53
-rw-r--r--openbsc/src/nat/bsc_nat.c23
2 files changed, 70 insertions, 6 deletions
diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c
index 858a15c5..f760ad62 100644
--- a/openbsc/src/bsc_msc_ip.c
+++ b/openbsc/src/bsc_msc_ip.c
@@ -60,13 +60,17 @@ static struct log_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *config_file = "openbsc.cfg";
static char *msc_address = NULL;
-static struct bsc_msc_connection *msc_con;
static struct in_addr local_addr;
static LLIST_HEAD(active_connections);
static struct write_queue mgcp_agent;
static const char *rf_ctl = NULL;
extern int ipacc_rtp_direct;
+/* msc handling */
+static struct bsc_msc_connection *msc_con;
+static struct timer_list msc_ping_timeout;
+static struct timer_list msc_pong_timeout;
+
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
extern int bsc_shutdown_net(struct gsm_network *net);
@@ -867,10 +871,51 @@ static void msc_connection_was_lost(struct bsc_msc_connection *msc)
bss_force_close(bss);
}
+ bsc_del_timer(&msc_ping_timeout);
+ bsc_del_timer(&msc_pong_timeout);
+
msc->is_authenticated = 0;
bsc_msc_schedule_connect(msc);
}
+static void msc_pong_timeout_cb(void *data)
+{
+ LOGP(DMSC, LOGL_ERROR, "MSC didn't answer PING. Closing connection.\n");
+ bsc_msc_lost(msc_con);
+}
+
+static void send_ping(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(4096, 128, "ping");
+ if (!msg) {
+ LOGP(DMSC, LOGL_ERROR, "Failed to create PING.\n");
+ return;
+ }
+
+ msg->l2h = msgb_put(msg, 1);
+ msg->l2h[0] = IPAC_MSGT_PING;
+
+ msc_queue_write(msg, IPAC_PROTO_IPACCESS);
+}
+
+static void msc_ping_timeout_cb(void *data)
+{
+ send_ping();
+
+ /* send another ping in 20 seconds */
+ bsc_schedule_timer(&msc_ping_timeout, 20, 0);
+
+ /* also start a pong timer */
+ bsc_schedule_timer(&msc_pong_timeout, 5, 0);
+}
+
+static void msc_connection_connected(struct bsc_msc_connection *con)
+{
+ msc_ping_timeout_cb(con);
+}
+
/*
* callback with IP access data
*/
@@ -903,6 +948,8 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
initialize_if_needed();
else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
send_id_get_response(bfd->fd);
+ } else if (msg->l2h[0] == IPAC_MSGT_PONG) {
+ bsc_del_timer(&msc_pong_timeout);
}
} else if (hh->proto == IPAC_PROTO_SCCP) {
sccp_system_incoming(msg);
@@ -1131,7 +1178,11 @@ int main(int argc, char **argv)
exit(1);
}
+ msc_ping_timeout.cb = msc_ping_timeout_cb;
+ msc_pong_timeout.cb = msc_pong_timeout_cb;
+
msc_con->connection_loss = msc_connection_was_lost;
+ msc_con->connected = msc_connection_connected;
msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
msc_con->write_queue.write_cb = msc_sccp_do_write;
bsc_msc_connect(msc_con);
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index ca018e0c..a60efd07 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -117,6 +117,15 @@ static void send_ping(struct bsc_connection *bsc)
bsc_send_data(bsc, id_ping, sizeof(id_ping), IPAC_PROTO_IPACCESS);
}
+static void send_pong(struct bsc_connection *bsc)
+{
+ static const u_int8_t id_pong[] = {
+ IPAC_MSGT_PONG,
+ };
+
+ bsc_send_data(bsc, id_pong, sizeof(id_pong), IPAC_PROTO_IPACCESS);
+}
+
static void bsc_pong_timeout(void *_bsc)
{
struct bsc_connection *bsc = _bsc;
@@ -646,6 +655,7 @@ static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
int error;
struct bsc_connection *bsc = bfd->data;
struct msgb *msg = ipaccess_read_msg(bfd, &error);
+ struct ipaccess_head *hh;
if (!msg) {
if (error == 0)
@@ -665,15 +675,18 @@ static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
/* Handle messages from the BSC */
- if (bsc->authenticated) {
- struct ipaccess_head *hh;
- hh = (struct ipaccess_head *) msg->data;
+ hh = (struct ipaccess_head *) msg->data;
- /* stop the pong timeout */
- if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_PONG) {
+ /* stop the pong timeout */
+ if (hh->proto == IPAC_PROTO_IPACCESS) {
+ if (msg->l2h[0] == IPAC_MSGT_PONG) {
bsc_del_timer(&bsc->pong_timeout);
msgb_free(msg);
return 0;
+ } else if (msg->l2h[0] == IPAC_MSGT_PING) {
+ send_pong(bsc);
+ msgb_free(msg);
+ return 0;
}
}