From e827812051f1597db89da2b90e2899b5cd1955ea Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Mon, 31 Mar 2014 13:42:11 +0200 Subject: [PATCH] ipa: Use enhanced ipa_msg_recv_buffered() to cope with partioned IPA messages The old ipa_msg_recv() implementation didn't support partial receive, so IPA connections got disconnected when this happened. This patch adds the handling of the temporary message buffers and uses ipa_msg_recv_buffered(). It has been successfully tested by jerlbeck with osmo-nitb and osmo-bsc. Ticket: OW#768 Sponsored-by: On-Waves ehf --- openbsc/configure.ac | 2 +- openbsc/include/openbsc/bsc_msc.h | 2 ++ openbsc/include/openbsc/bsc_nat.h | 5 +++++ openbsc/include/openbsc/control_cmd.h | 3 +++ openbsc/src/libbsc/bsc_msc.c | 10 ++++++++++ openbsc/src/libctrl/control_if.c | 5 ++++- openbsc/src/osmo-bsc/osmo_bsc_msc.c | 6 ++++-- openbsc/src/osmo-bsc_nat/bsc_nat.c | 19 +++++++++++++++---- openbsc/src/osmo-bsc_nat/bsc_ussd.c | 8 ++++++-- 9 files changed, 50 insertions(+), 10 deletions(-) diff --git a/openbsc/configure.ac b/openbsc/configure.ac index 5d29af717..978f52660 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -25,7 +25,7 @@ AC_SUBST(LIBRARY_DL) PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.6.4) PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0) PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.6.0) -PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.1.0) +PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.2.0) PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.6.4) # Enabke/disable the NAT? diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h index 647f47e56..0adbd266e 100644 --- a/openbsc/include/openbsc/bsc_msc.h +++ b/openbsc/include/openbsc/bsc_msc.h @@ -48,6 +48,8 @@ struct bsc_msc_connection { void (*connected) (struct bsc_msc_connection *); struct osmo_timer_list reconnect_timer; struct osmo_timer_list timeout_timer; + + struct msgb *pending_msg; }; struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dest); diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index fe8e52137..7bd582cf6 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -97,6 +97,9 @@ struct bsc_connection { /* the fd we use to communicate */ struct osmo_wqueue write_queue; + /* incoming message buffer */ + struct msgb *pending_msg; + /* the BSS associated */ struct bsc_config *cfg; @@ -343,6 +346,8 @@ struct bsc_nat_ussd_con { struct bsc_nat *nat; int authorized; + struct msgb *pending_msg; + struct osmo_timer_list auth_timeout; }; diff --git a/openbsc/include/openbsc/control_cmd.h b/openbsc/include/openbsc/control_cmd.h index 725dce061..8aede15df 100644 --- a/openbsc/include/openbsc/control_cmd.h +++ b/openbsc/include/openbsc/control_cmd.h @@ -39,6 +39,9 @@ struct ctrl_connection { /* The queue for sending data back */ struct osmo_wqueue write_queue; + /* Buffer for partial input data */ + struct msgb *pending_msg; + /* Callback if the connection was closed */ void (*closed_cb)(struct ctrl_connection *conn); diff --git a/openbsc/src/libbsc/bsc_msc.c b/openbsc/src/libbsc/bsc_msc.c index 1a0f78aea..a24efabb0 100644 --- a/openbsc/src/libbsc/bsc_msc.c +++ b/openbsc/src/libbsc/bsc_msc.c @@ -42,6 +42,13 @@ static void connection_loss(struct bsc_msc_connection *con) fd = &con->write_queue.bfd; + if (con->pending_msg) { + LOGP(DMSC, LOGL_ERROR, + "MSC(%s) dropping incomplete message.\n", con->name); + msgb_free(con->pending_msg); + con->pending_msg = NULL; + } + close(fd->fd); fd->fd = -1; fd->cb = osmo_wqueue_bfd_cb; @@ -162,6 +169,9 @@ int bsc_msc_connect(struct bsc_msc_connection *con) con->is_connected = 0; + msgb_free(con->pending_msg); + con->pending_msg = NULL; + fd = &con->write_queue.bfd; fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); fd->priv_nr = 1; diff --git a/openbsc/src/libctrl/control_if.c b/openbsc/src/libctrl/control_if.c index 2727d0dd3..ca59d8c6d 100644 --- a/openbsc/src/libctrl/control_if.c +++ b/openbsc/src/libctrl/control_if.c @@ -123,6 +123,7 @@ static void control_close_conn(struct ctrl_connection *ccon) llist_del(&ccon->list_entry); if (ccon->closed_cb) ccon->closed_cb(ccon); + msgb_free(ccon->pending_msg); talloc_free(ccon); } @@ -140,8 +141,10 @@ static int handle_control_read(struct osmo_fd * bfd) queue = container_of(bfd, struct osmo_wqueue, bfd); ccon = container_of(queue, struct ctrl_connection, write_queue); - ret = ipa_msg_recv(bfd->fd, &msg); + ret = ipa_msg_recv_buffered(bfd->fd, &msg, &ccon->pending_msg); if (ret <= 0) { + if (ret == -EAGAIN) + return 0; if (ret == 0) LOGP(DCTRL, LOGL_INFO, "The control connection was closed\n"); else diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c index 603398551..04e9cf3a7 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c @@ -247,13 +247,15 @@ static void osmo_ext_handle(struct osmo_msc_data *msc, struct msgb *msg) static int ipaccess_a_fd_cb(struct osmo_fd *bfd) { - struct msgb *msg; + struct msgb *msg = NULL; struct ipaccess_head *hh; struct osmo_msc_data *data = (struct osmo_msc_data *) bfd->data; int ret; - ret = ipa_msg_recv(bfd->fd, &msg); + ret = ipa_msg_recv_buffered(bfd->fd, &msg, &data->msc_con->pending_msg); if (ret <= 0) { + if (ret == -EAGAIN) + return 0; if (ret == 0) { LOGP(DMSC, LOGL_ERROR, "The connection to the MSC was lost.\n"); bsc_msc_lost(data->msc_con); diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index d9fc0ca48..524186a55 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -796,14 +796,16 @@ static void msc_send_reset(struct bsc_msc_connection *msc_con) static int ipaccess_msc_read_cb(struct osmo_fd *bfd) { struct bsc_msc_connection *msc_con; - struct msgb *msg; + struct msgb *msg = NULL; struct ipaccess_head *hh; int ret; msc_con = (struct bsc_msc_connection *) bfd->data; - ret = ipa_msg_recv(bfd->fd, &msg); + ret = ipa_msg_recv_buffered(bfd->fd, &msg, &msc_con->pending_msg); if (ret <= 0) { + if (ret == -EAGAIN) + return 0; if (ret == 0) LOGP(DNAT, LOGL_FATAL, "The connection the MSC(%s) was lost, exiting\n", @@ -912,6 +914,13 @@ void bsc_close_connection(struct bsc_connection *connection) osmo_wqueue_clear(&connection->write_queue); llist_del(&connection->list_entry); + if (connection->pending_msg) { + LOGP(DNAT, LOGL_ERROR, "Dropping partial message on connection %d.\n", + connection->cfg->nr); + msgb_free(connection->pending_msg); + connection->pending_msg = NULL; + } + talloc_free(connection); } @@ -1206,13 +1215,15 @@ exit3: static int ipaccess_bsc_read_cb(struct osmo_fd *bfd) { struct bsc_connection *bsc = bfd->data; - struct msgb *msg; + struct msgb *msg = NULL; struct ipaccess_head *hh; struct ipaccess_head_ext *hh_ext; int ret; - ret = ipa_msg_recv(bfd->fd, &msg); + ret = ipa_msg_recv_buffered(bfd->fd, &msg, &bsc->pending_msg); if (ret <= 0) { + if (ret == -EAGAIN) + return 0; if (ret == 0) LOGP(DNAT, LOGL_ERROR, "The connection to the BSC Nr: %d was lost. Cleaning it\n", diff --git a/openbsc/src/osmo-bsc_nat/bsc_ussd.c b/openbsc/src/osmo-bsc_nat/bsc_ussd.c index 8da818119..5f073bf4f 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_ussd.c +++ b/openbsc/src/osmo-bsc_nat/bsc_ussd.c @@ -66,6 +66,8 @@ static void bsc_nat_ussd_destroy(struct bsc_nat_ussd_con *con) osmo_fd_unregister(&con->queue.bfd); osmo_timer_del(&con->auth_timeout); osmo_wqueue_clear(&con->queue); + + msgb_free(con->pending_msg); talloc_free(con); } @@ -117,12 +119,14 @@ static int forward_sccp(struct bsc_nat *nat, struct msgb *msg) static int ussd_read_cb(struct osmo_fd *bfd) { struct bsc_nat_ussd_con *conn = bfd->data; - struct msgb *msg; + struct msgb *msg = NULL; struct ipaccess_head *hh; int ret; - ret = ipa_msg_recv(bfd->fd, &msg); + ret = ipa_msg_recv_buffered(bfd->fd, &msg, &conn->pending_msg); if (ret <= 0) { + if (ret == -EAGAIN) + return 0; LOGP(DNAT, LOGL_ERROR, "USSD Connection was lost.\n"); bsc_nat_ussd_destroy(conn); return -1;