aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp <pmaier@sysmocom.de>2016-12-09 17:28:10 +0100
committerPhilipp <pmaier@sysmocom.de>2017-01-12 12:20:41 +0100
commit9de825adcb558a9d44f8b205904092a0a8487692 (patch)
treea614062d822a205272e4330631db61687171c374
parent047778f8fb8c9315981d7c7cfa6a5e6271be6d4a (diff)
unixsocket: make socket connection fault tolerant
When the l2tpd is killed osmo-nitb will permanently loose connection to the BSS, even if l2tpd is restarted. This commit adds some fault tolerance to make osmo-nitb automatically reconnect as soon as the l2tpd socket is available again
-rw-r--r--src/input/unixsocket.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/src/input/unixsocket.c b/src/input/unixsocket.c
index 554decd..f434059 100644
--- a/src/input/unixsocket.c
+++ b/src/input/unixsocket.c
@@ -42,17 +42,33 @@ void *tall_unixsocket_ctx;
struct unixsocket_line {
struct osmo_fd fd;
+ struct osmo_timer_list timer;
};
+static int unixsocket_line_update(struct e1inp_line *line);
static int ts_want_write(struct e1inp_ts *e1i_ts);
static int unixsocket_exception_cb(struct osmo_fd *bfd)
{
struct e1inp_line *line = bfd->data;
- LOGP(DLINP, LOGL_ERROR, "unixsocket: closing socket. Exception cb called.\n");
+ LOGP(DLINP, LOGL_ERROR,
+ "Socket connection failure, reconnecting... (line=%p, fd=%d)\n",
+ line, bfd->fd);
+
+ /* Unregister faulty file descriptor from select loop */
+ if(osmo_fd_register_check(bfd)) {
+ LOGP(DLINP, LOGL_DEBUG,
+ "removing inactive socket from select loop... (line=%p, fd=%d)\n",
+ line, bfd->fd);
+ osmo_fd_unregister(bfd);
+ }
+
+ /* Close faulty file descriptor */
close(bfd->fd);
+ unixsocket_line_update(line);
+
return 0;
}
@@ -75,6 +91,9 @@ static int unixsocket_read_cb(struct osmo_fd *bfd)
}
msgb_put(msg, ret);
+ LOGP(DLMI, LOGL_DEBUG, "rx msg: %s (fd=%d)\n",
+ osmo_hexdump_nospc(msg->data, msg->len), bfd->fd);
+
return e1inp_rx_ts_lapd(&line->ts[0], msg);
}
@@ -99,7 +118,8 @@ static int unixsocket_write_cb(struct osmo_fd *bfd)
msg = e1inp_tx_ts(e1i_ts, &sign_link);
if (!msg) {
/* no message after tx delay timer */
- LOGP(DLINP, LOGL_INFO, "unixsocket: no message available");
+ LOGP(DLINP, LOGL_INFO,
+ "no message available (line=%p)\n", line);
return 0;
}
@@ -109,7 +129,8 @@ static int unixsocket_write_cb(struct osmo_fd *bfd)
osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
- LOGP(DLINP, LOGL_INFO, "unixsocket: sending: %s", msgb_hexdump(msg));
+ LOGP(DLINP, LOGL_INFO, "sending: %s (line=%p)\n",
+ msgb_hexdump(msg), line);
lapd_transmit(e1i_ts->lapd, sign_link->tei,
sign_link->sapi, msg);
@@ -147,6 +168,9 @@ static void unixsocket_write_msg(struct msgb *msg, void *cbdata)
struct osmo_fd *bfd = cbdata;
int ret;
+ LOGP(DLMI, LOGL_DEBUG, "tx msg: %s (fd=%d)\n",
+ osmo_hexdump_nospc(msg->data, msg->len), bfd->fd);
+
ret = write(bfd->fd, msg->data, msg->len);
msgb_free(msg);
if (ret == -1)
@@ -162,44 +186,61 @@ static int unixsocket_line_update(struct e1inp_line *line)
int ret = 0;
int i;
- LOGP(DLINP, LOGL_NOTICE, "unixsocket: line update\n");
+ LOGP(DLINP, LOGL_NOTICE, "line update (line=%p)\n", line);
if (!line->driver_data)
line->driver_data = talloc_zero(line, struct unixsocket_line);
if (!line->driver_data) {
- LOGP(DLINP, LOGL_ERROR, "unixsocket: OOM in line update\n");
+ LOGP(DLINP, LOGL_ERROR,
+ "OOM in line update (line=%p)\n", line);
return -ENOMEM;
}
config = line->driver_data;
-
config->fd.data = line;
config->fd.when = BSC_FD_READ;
config->fd.cb = unixsocket_cb;
- ret = osmo_sock_unix_init(SOCK_SEQPACKET, 0, sock_path, OSMO_SOCK_F_CONNECT);
+ /* Open unix domain socket */
+ ret = osmo_sock_unix_init(SOCK_SEQPACKET, 0, sock_path,
+ OSMO_SOCK_F_CONNECT);
if (ret < 0) {
- talloc_free(config);
+ /* Note: We will not free the allocated driver_data memory if
+ * opening the socket fails. The caller may want to call this
+ * function multiple times using config->fd.data as line
+ * parameter. Freeing now would destroy that reference. */
+ LOGP(DLINP, LOGL_ERROR,
+ "unable to open socket: %s (line=%p, fd=%d)\n", sock_path,
+ line, config->fd.fd);
return ret;
}
-
+ LOGP(DLINP, LOGL_DEBUG,
+ "successfully opend (new) socket (line=%p, fd=%d, ret=%d)\n",
+ line, config->fd.fd, ret);
config->fd.fd = ret;
+
+ /* Register socket in select loop */
if (osmo_fd_register(&config->fd) < 0) {
+ LOGP(DLINP, LOGL_ERROR,
+ "error registering new socket (line=%p, fd=%d)\n",
+ line, config->fd.fd);
close(config->fd.fd);
return -EIO;
}
+ /* Set line parameter */
for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
struct e1inp_ts *e1i_ts = &line->ts[i];
-
- if (!e1i_ts->lapd)
+ if (!e1i_ts->lapd) {
e1i_ts->lapd = lapd_instance_alloc(1,
- unixsocket_write_msg, &config->fd, e1inp_dlsap_up,
- e1i_ts, &lapd_profile_abis);
+ unixsocket_write_msg, &config->fd,
+ e1inp_dlsap_up, e1i_ts, &lapd_profile_abis);
+ }
}
- /* Ensure Superchannel is turned of when a new connection is made */
+ /* Ensure ericsson-superchannel is turned of when
+ * a new connection is made */
e1inp_ericsson_set_altc(line, 0);
return ret;