diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-05-02 19:28:59 +0800 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-05-02 19:31:14 +0800 |
commit | 6782cea4bf33f4142fd4aa65467149a34c35725a (patch) | |
tree | 581bb27bb2c68588e16ce2cf173785dcdc69b455 | |
parent | ec7ecab66f530bb00f6d9d166a2cbb1e89bbd713 (diff) |
nat: Send a IPA PING down the stream and wait for the pong.
We will send a ping every 20 seconds and if we have no pong
within 5 seconds we will close down the BSC connection and
wait for a reconnect. We will start this after having
authenticated the BSC and we stop the timer when destructing
the BSC connection.
-rw-r--r-- | openbsc/include/openbsc/bsc_nat.h | 4 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 55 |
2 files changed, 59 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 28ed4e804..d72e3b4ba 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -93,6 +93,10 @@ struct bsc_connection { /* a timeout node */ struct timer_list id_timeout; + /* pong timeout */ + struct timer_list ping_timeout; + struct timer_list pong_timeout; + /* a back pointer */ struct bsc_nat *nat; }; diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c index d9cf5e54f..ca018e0c6 100644 --- a/openbsc/src/nat/bsc_nat.c +++ b/openbsc/src/nat/bsc_nat.c @@ -108,6 +108,46 @@ static void send_reset_ack(struct bsc_connection *bsc) bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack), IPAC_PROTO_SCCP); } +static void send_ping(struct bsc_connection *bsc) +{ + static const u_int8_t id_ping[] = { + IPAC_MSGT_PING, + }; + + bsc_send_data(bsc, id_ping, sizeof(id_ping), IPAC_PROTO_IPACCESS); +} + +static void bsc_pong_timeout(void *_bsc) +{ + struct bsc_connection *bsc = _bsc; + + LOGP(DNAT, LOGL_ERROR, "BSC Nr: %d PONG timeout.\n", bsc->cfg->nr); + bsc_close_connection(bsc); +} + +static void bsc_ping_timeout(void *_bsc) +{ + struct bsc_connection *bsc = _bsc; + + send_ping(bsc); + + /* send another ping in 20 seconds */ + bsc_schedule_timer(&bsc->ping_timeout, 20, 0); + + /* also start a pong timer */ + bsc_schedule_timer(&bsc->pong_timeout, 5, 0); +} + +static void start_ping_pong(struct bsc_connection *bsc) +{ + bsc->pong_timeout.data = bsc; + bsc->pong_timeout.cb = bsc_pong_timeout; + bsc->ping_timeout.data = bsc; + bsc->ping_timeout.cb = bsc_ping_timeout; + + bsc_ping_timeout(bsc); +} + static void send_id_ack(struct bsc_connection *bsc) { static const u_int8_t id_ack[] = { @@ -437,6 +477,8 @@ void bsc_close_connection(struct bsc_connection *connection) /* stop the timeout timer */ bsc_del_timer(&connection->id_timeout); + bsc_del_timer(&connection->ping_timeout); + bsc_del_timer(&connection->pong_timeout); /* remove all SCCP connections */ llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) { @@ -490,6 +532,7 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc bsc->cfg = conf; bsc_del_timer(&bsc->id_timeout); LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d\n", conf->nr, conf->lac); + start_ping_pong(bsc); return; } } @@ -622,6 +665,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; + + /* stop the pong timeout */ + if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_PONG) { + bsc_del_timer(&bsc->pong_timeout); + msgb_free(msg); + return 0; + } + } + /* FIXME: Currently no PONG is sent to the BSC */ /* FIXME: Currently no ID ACK is sent to the BSC */ forward_sccp_to_msc(bsc, msg); |