pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-abis/+/38983?usp=email )
Change subject: WIP: ipaccess: Conver BSC OML & RSL link to use stream_srv
......................................................................
WIP: ipaccess: Conver BSC OML & RSL link to use stream_srv
This in turn allows running BSC Abis interfaces through io-uring
backend, which should provide performance improvements when used.
TODO: Re-introduce the sign.delay Tx timer to fix issues with ancient
nanoBTS.
TODO: Get rid of ipaccess_fd_cb() in osmo-bsc.git ipaccess-config by
implementing its own e1i_line ipaccess driver there (due to many
peculiarities: tcp/ipa cli instead of srv, different OML port).
Related: SYS#7063
Related: OS#5755
Related: OS#5756
Change-Id: Idf241c8f2fdb86d090d4132a9b316b7236402232
---
M include/osmocom/abis/ipaccess.h
M src/input/ipaccess.c
2 files changed, 270 insertions(+), 333 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/83/38983/1
diff --git a/include/osmocom/abis/ipaccess.h b/include/osmocom/abis/ipaccess.h
index b1fe2c9..dbf8a64 100644
--- a/include/osmocom/abis/ipaccess.h
+++ b/include/osmocom/abis/ipaccess.h
@@ -5,6 +5,7 @@
#include <osmocom/gsm/protocol/ipaccess.h>
/* quick solution to get openBSC's ipaccess tools working. */
-extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what);
+// TODO: get rid of this.... used by osmo-bsc.git ipaccess-proxy and ipacess-config...
+//extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what);
#endif /* _OSMO_ABIS_IPACCESS_H */
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index af6e39d..2a58de5 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -90,73 +90,20 @@
}
}
-static int ipaccess_drop(struct osmo_fd *bfd, struct e1inp_line *line)
-{
- int ret = 1;
- struct e1inp_ts *e1i_ts = ipaccess_line_ts(bfd, line);
- e1inp_line_get2(line, __func__);
-
- ipaccess_keepalive_fsm_cleanup(e1i_ts);
-
- /* Error case: we did not see any ID_RESP yet for this socket. */
- if (bfd->fd != -1) {
- LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "Forcing socket shutdown\n");
- osmo_fd_unregister(bfd);
- close(bfd->fd);
- bfd->fd = -1;
- switch (line->ops->cfg.ipa.role) {
- case E1INP_LINE_R_BSC:
- /* This is BSC code, ipaccess_drop() is only called for
- accepted() sockets, hence the bfd holds a reference to
- e1inp_line in ->data that needs to be released */
- OSMO_ASSERT(bfd->data == line);
- bfd->data = NULL;
- e1inp_line_put2(line, "ipa_bfd");
- break;
- case E1INP_LINE_R_BTS:
- /* BTS code: bfd->data contains pointer to struct
- * ipa_client_conn. Leave it alive so it reconnects.
- */
- break;
- default:
- break;
- }
- ret = -ENOENT;
- } else {
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR,
- "Forcing socket shutdown with no signal link set\n");
- }
-
- msgb_free(e1i_ts->pending_msg);
- e1i_ts->pending_msg = NULL;
-
- /* e1inp_sign_link_destroy releases the socket descriptors for us. */
- if (line->ops->sign_link_down)
- line->ops->sign_link_down(line);
-
- e1inp_line_put2(line, __func__);
- return ret;
-}
-
static void ipa_bsc_keepalive_write_server_cb(struct osmo_fsm_inst *fi, void *conn,
struct msgb *msg)
{
- struct osmo_fd *bfd = (struct osmo_fd *)conn;
- write(bfd->fd, msg->data, msg->len);
- msgb_free(msg);
+ struct osmo_stream_srv *srv = (struct osmo_stream_srv *)conn;
+ osmo_stream_srv_send(srv, msg);
}
static int ipa_bsc_keepalive_timeout_cb(struct osmo_fsm_inst *fi, void *data)
{
- struct osmo_fd *bfd = (struct osmo_fd *)data;
-
- if (bfd->fd == -1)
- return 1;
-
- ipaccess_drop(bfd, (struct e1inp_line *)bfd->data);
+ struct osmo_stream_srv *srv = (struct osmo_stream_srv *)data;
+ osmo_stream_srv_destroy(srv);
return 1;
}
-static void ipaccess_bsc_keepalive_fsm_alloc(struct e1inp_ts *e1i_ts, struct osmo_fd
*bfd, const char *id)
+static void ipaccess_bsc_keepalive_fsm_alloc(struct e1inp_ts *e1i_ts, struct
osmo_stream_srv *conn, const char *id)
{
struct e1inp_line *line = e1i_ts->line;
struct osmo_fsm_inst *ka_fsm;
@@ -165,7 +112,7 @@
if (!line->ipa_kap)
return;
- ka_fsm = ipa_generic_conn_alloc_keepalive_fsm(tall_ipa_ctx, bfd, line->ipa_kap, id);
+ ka_fsm = ipa_generic_conn_alloc_keepalive_fsm(conn, conn, line->ipa_kap, id);
e1i_ts->driver.ipaccess.ka_fsm = ka_fsm;
if (!ka_fsm) {
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Failed to allocate IPA keepalive
FSM\n");
@@ -250,22 +197,37 @@
return cli;
}
-/* Returns -1 on error, and 0 or 1 on success. If -1 or 1 is returned, line has
- * been released and should not be used anymore by the caller. */
-static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
- struct osmo_fd *bfd)
+static inline struct osmo_stream_srv *ipaccess_bts_e1i_ts_stream_srv(const struct
e1inp_ts *e1i_ts)
{
+ OSMO_ASSERT(e1i_ts);
+ struct osmo_stream_srv *conn = e1i_ts->driver.ipaccess.fd.data;
+ /* conn may be NULL here, if we are called by user during sign_link_up()
+ * and hence before we finished to internally move the ipaccess conn under
+ * the proper final line/ts object.
+ */
+ return conn;
+}
+
+static int ipaccess_bsc_write_cb(struct e1inp_ts *e1i_ts);
+
+/* Returns -1 on error, and 0 or 1 on success. If -1 or 1 is returned, line has
+ * been released and should not be used anymore by the caller.
+ * msg is always freed upon return.
+ */
+static int ipaccess_bsc_rcvmsg(struct osmo_stream_srv *conn, struct msgb *msg)
+{
+ struct e1inp_ts *e1i_ts = osmo_stream_srv_get_data(conn);
+ struct e1inp_line *line = e1i_ts->line;
+ struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
struct tlv_parsed tlvp;
uint8_t msg_type = *(msg->l2h);
struct ipaccess_unit unit_data = {};
struct e1inp_sign_link *sign_link;
char *unitid;
int len, ret;
- struct e1inp_ts *e1i_ts;
struct osmo_fsm_inst *ka_fsm;
/* peek the pong for our keepalive fsm */
- e1i_ts = ipaccess_line_ts(bfd, line);
ka_fsm = e1i_ts->driver.ipaccess.ka_fsm;
if (ka_fsm && msg_type == IPAC_MSGT_PONG)
ipa_keepalive_fsm_pong_received(ka_fsm);
@@ -278,7 +240,7 @@
goto err;
case 1:
/* this is an IPA control message, skip further processing */
- return 0;
+ goto ret_skip;
case 0:
/* this is not an IPA control message, continue */
break;
@@ -329,17 +291,16 @@
goto err;
}
- ipaccess_bsc_keepalive_fsm_alloc(e1i_ts, bfd, "oml_bsc_to_bts");
+ ipaccess_bsc_keepalive_fsm_alloc(e1i_ts, conn, "oml_bsc_to_bts");
} else if (bfd->priv_nr == E1INP_SIGN_RSL) {
- struct e1inp_ts *ts;
+ struct e1inp_ts *new_ts;
struct osmo_fd *newbfd;
struct e1inp_line *new_line;
char tcp_stat_name[64];
sign_link =
- line->ops->sign_link_up(&unit_data, line,
- E1INP_SIGN_RSL);
+ line->ops->sign_link_up(&unit_data, line, E1INP_SIGN_RSL);
if (sign_link == NULL) {
LOGPIL(line, DLINP, LOGL_ERROR, "Unable to set signal link, closing
socket.\n");
goto err;
@@ -352,37 +313,35 @@
if (new_line == line) {
LOGPIL(line, DLINP, LOGL_ERROR, "Fix your BSC, you should use the "
"E1 line used by the OML link for your RSL link.\n");
- return 0;
+ goto ret_skip;
}
+
+ /* Attach srv_conn to new line+ts: */
e1inp_line_get2(new_line, "ipa_bfd");
- ts = e1inp_line_ipa_rsl_ts(new_line, unit_data.trx_id);
- newbfd = &ts->driver.ipaccess.fd;
+ new_ts = e1inp_line_ipa_rsl_ts(new_line, unit_data.trx_id);
+ newbfd = &new_ts->driver.ipaccess.fd;
OSMO_ASSERT(newbfd != bfd);
+ osmo_fd_setup(newbfd, bfd->fd, 0, NULL, conn, E1INP_SIGN_RSL + unit_data.trx_id);
+ osmo_stream_srv_set_data(conn, new_ts);
- /* preserve 'newbfd->when' flags potentially set by sign_link_up() */
- osmo_fd_setup(newbfd, bfd->fd, newbfd->when | bfd->when, bfd->cb,
- new_line, E1INP_SIGN_RSL + unit_data.trx_id);
-
-
- /* now we can release the dummy RSL line (old temporary bfd). */
- osmo_fd_unregister(bfd);
+ /* Now we can release the old temporar ydummy RSL line+ts: */
bfd->fd = -1;
- /* bfd->data holds a reference to line, drop it */
- OSMO_ASSERT(bfd->data == line);
+ /* conn holds a reference to old line, drop it */
+ OSMO_ASSERT(bfd->data == conn);
bfd->data = NULL;
e1inp_line_put2(line, "ipa_bfd");
- ret = osmo_fd_register(newbfd);
- if (ret < 0) {
- LOGPITS(ts, DLINP, LOGL_ERROR, "could not register FD\n");
- goto err;
- }
snprintf(tcp_stat_name, sizeof(tcp_stat_name), "site.%u.bts.%u.ipa-rsl.%u",
unit_data.site_id, unit_data.bts_id, unit_data.trx_id);
osmo_stats_tcp_osmo_fd_register(newbfd, tcp_stat_name);
- e1i_ts = ipaccess_line_ts(newbfd, new_line);
- ipaccess_bsc_keepalive_fsm_alloc(e1i_ts, newbfd, "rsl_bsc_to_bts");
+ ipaccess_bsc_keepalive_fsm_alloc(new_ts, conn, "rsl_bsc_to_bts");
+
+ /* Now that we attached the srv_conn to the e1ts, transmit packets which may been
enqueued
+ * by user during sign_link_up() and which were delayed due to no srv_conn found: */
+ ipaccess_bsc_write_cb(new_ts);
+ /* Conn is not freed here, so we need to free msgb. */
+ msgb_free(msg);
return 1;
}
break;
@@ -390,86 +349,14 @@
LOGPIL(line, DLINP, LOGL_ERROR, "Unknown IPA message type\n");
goto err;
}
+
+ret_skip:
+ msgb_free(msg);
return 0;
err:
- if (bfd->fd != -1) {
- osmo_fd_unregister(bfd);
- close(bfd->fd);
- bfd->fd = -1;
- /* This is a BSC accepted socket, bfd->data holds a reference to line, drop it */
- OSMO_ASSERT(bfd->data == line);
- bfd->data = NULL;
- e1inp_line_put2(line, "ipa_bfd");
- }
- return -1;
-}
-
-/* Returns -EBADF if bfd cannot be used by the caller anymore after return. */
-static int handle_ts1_read(struct osmo_fd *bfd)
-{
- struct e1inp_line *line = bfd->data;
- unsigned int ts_nr = bfd->priv_nr;
- struct e1inp_ts *e1i_ts;
- struct e1inp_sign_link *link;
- struct ipaccess_head *hh;
- struct msgb *msg = NULL;
- int ret, rc;
-
- e1i_ts = ipaccess_line_ts(bfd, line);
- ret = ipa_msg_recv_buffered(bfd->fd, &msg, &e1i_ts->pending_msg);
- if (ret < 0) {
- if (ret == -EAGAIN)
- return 0;
- LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "Sign link problems, closing socket. Reason:
%s\n",
- strerror(-ret));
- goto err;
- } else if (ret == 0) {
- LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "Sign link vanished, dead socket\n");
- goto err;
- }
- LOGPITS(e1i_ts, DLMI, LOGL_DEBUG, "RX %u: %s\n", ts_nr,
osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
-
- hh = (struct ipaccess_head *) msg->data;
- if (hh->proto == IPAC_PROTO_IPACCESS) {
- ret = ipaccess_rcvmsg(line, msg, bfd);
- /* BIG FAT WARNING: bfd might no longer exist here (ret != 0),
- * since ipaccess_rcvmsg() might have free'd it !!! */
- msgb_free(msg);
- return ret != 0 ? -EBADF : 0;
- } else if (e1i_ts->type == E1INP_TS_TYPE_NONE) {
- /* this sign link is not know yet.. complain. */
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Timeslot is not configured.\n");
- goto err_msg;
- }
-
- link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0);
- if (!link) {
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "no matching signalling link for
hh->proto=0x%02x\n", hh->proto);
- goto err_msg;
- }
- msg->dst = link;
-
- /* XXX better use e1inp_ts_rx? */
- if (!e1i_ts->line->ops->sign_link) {
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Fix your application, no action set for
signalling messages.\n");
- goto err_msg;
- }
- rc = e1i_ts->line->ops->sign_link(msg);
- if (rc < 0) {
- /* Don't close the signalling link if the upper layers report
- * an error, that's too strict. BTW, the signalling layer is
- * resposible for releasing the message.
- */
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Bad signalling message, sign_link returned
error: %s.\n",
- strerror(-rc));
- }
-
- return rc;
-err_msg:
msgb_free(msg);
-err:
- ipaccess_drop(bfd, line);
- return -EBADF;
+ osmo_stream_srv_destroy(conn);
+ return -1;
}
static void ipaccess_close(struct e1inp_sign_link *sign_link)
@@ -479,6 +366,7 @@
struct e1inp_line *line = e1i_ts->line;
struct osmo_fsm_inst *ka_fsm = e1i_ts->driver.ipaccess.ka_fsm;
struct osmo_stream_cli *cli;
+ struct osmo_stream_srv *conn;
/* depending on caller the fsm might be dead */
if (ka_fsm)
@@ -495,19 +383,24 @@
bfd->fd = -1; /* Compatibility with older implementations */
break;
case E1INP_LINE_R_BSC:
- default:
- if (bfd->fd != -1) {
- osmo_fd_unregister(bfd);
- close(bfd->fd);
- bfd->fd = -1;
- /* If The bfd holds a reference to e1inp_line in ->data (BSC
- * accepted() sockets), then release it */
- if (bfd->data == line) {
- bfd->data = NULL;
- e1inp_line_put2(line, "ipa_bfd");
- }
+ /* conn may be NULL here, if we are called by user during sign_link_up()
+ * ballback and hence before we finished to internally move the ipaccess conn
+ * under the proper final line/ts object:
+ */
+ conn = ipaccess_bts_e1i_ts_stream_srv(e1i_ts);
+ if (conn) {
+ osmo_stream_srv_destroy(conn);
+ } else {
+ LOGPITS(e1i_ts, DLINP, LOGL_DEBUG,
+ "ipaccess_close() on ts with no srv_conn, "
+ "probably called during sign_link_up() or sign_link_down() user cb.\n");
}
break;
+ default:
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR,
+ "ipaccess_close() for line with unknown role %d\n",
+ line->ops->cfg.ipa.role);
+ break;
}
}
@@ -562,6 +455,55 @@
return rc;
}
+static int ipaccess_bsc_send_msg(struct e1inp_ts *e1i_ts,
+ struct e1inp_sign_link *sign_link,
+ struct osmo_stream_srv *conn,
+ struct msgb *msg)
+{
+ switch (sign_link->type) {
+ case E1INP_SIGN_OML:
+ case E1INP_SIGN_RSL:
+ case E1INP_SIGN_OSMO:
+ break;
+ default:
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+ msg->l2h = msg->data;
+ ipa_prepend_header(msg, sign_link->tei);
+
+ LOGPITS(e1i_ts, DLMI, LOGL_DEBUG, "TX: %s\n", osmo_hexdump(msg->l2h,
msgb_l2len(msg)));
+ osmo_stream_srv_send(conn, msg);
+ return 0;
+}
+
+/* msg was enqueued in sign_link->tx_list.
+ * Pop it from that list, submit it to osmo_stream_srv. */
+static int ipaccess_bsc_write_cb(struct e1inp_ts *e1i_ts)
+{
+ int rc = 0;
+ struct osmo_stream_srv *srv = ipaccess_bts_e1i_ts_stream_srv(e1i_ts);
+
+ /* conn may be NULL here, if we are called by user during sign_link_up()
+ * ballback and hence before we finished to internally move the ipaccess conn
+ * under the proper final line/ts object:
+ */
+ if (!srv) {
+ LOGPITS(e1i_ts, DLMI, LOGL_DEBUG, "Delaying Tx on ts with no srv_conn\n");
+ return -ENODEV;
+ }
+
+ /* get the next msg for this timeslot */
+ while (e1i_ts_has_pending_tx_msgs(e1i_ts)) {
+ struct e1inp_sign_link *sign_link = NULL;
+ struct msgb *msg;
+ msg = e1inp_tx_ts(e1i_ts, &sign_link);
+ rc |= ipaccess_bsc_send_msg(e1i_ts, sign_link, srv, msg);
+ }
+ return rc;
+}
+
static int ts_want_write(struct e1inp_ts *e1i_ts)
{
enum e1inp_line_role role = E1INP_LINE_R_NONE;
@@ -576,118 +518,92 @@
/* msg was enqueued in sign_link->tx_list.
* Pop it from that list, submit it to osmo_stream_cli: */
return ipaccess_bts_write_cb(e1i_ts);
- case E1INP_LINE_R_NONE:
case E1INP_LINE_R_BSC:
+ /* msg was enqueued in sign_link->tx_list.
+ * Pop it from that list, submit it to osmo_stream_cli: */
+ return ipaccess_bsc_write_cb(e1i_ts);
+ case E1INP_LINE_R_NONE:
default:
- osmo_fd_write_enable(&e1i_ts->driver.ipaccess.fd);
- /* ipaccess_fd_cb will be called from main loop and tx the msgb. */
+ LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "want_write for ts with unknown role
%d!\n", role);
return 0;
}
}
-static void timeout_ts1_write(void *data)
+static int ipaccess_bsc_conn_read_cb(struct osmo_stream_srv *conn, int res, struct msgb
*msg)
{
- struct e1inp_ts *e1i_ts = (struct e1inp_ts *)data;
+ enum ipaccess_proto ipa_proto = osmo_ipa_msgb_cb_proto(msg);
+ struct e1inp_ts *e1i_ts = osmo_stream_srv_get_data(conn);
+ struct e1inp_sign_link *link;
+ int ret, rc;
- /* trigger write of ts1, due to tx delay timer */
- if (e1i_ts_has_pending_tx_msgs(e1i_ts))
- ts_want_write(e1i_ts);
-}
-
-static int __handle_ts1_write(struct osmo_fd *bfd, struct e1inp_line *line)
-{
- unsigned int ts_nr = bfd->priv_nr;
- struct e1inp_ts *e1i_ts;
- struct e1inp_sign_link *sign_link;
- struct msgb *msg;
- int ret;
-
- e1i_ts = ipaccess_line_ts(bfd, line);
-
- /* get the next msg for this timeslot */
- msg = e1inp_tx_ts(e1i_ts, &sign_link);
- if (!msg) {
- /* no message after tx delay timer */
- osmo_fd_write_disable(bfd);
- return 0;
- }
-
- switch (sign_link->type) {
- case E1INP_SIGN_OML:
- case E1INP_SIGN_RSL:
- case E1INP_SIGN_OSMO:
- break;
- default:
- /* leave WRITE flag enabled, come back for more msg */
- ret = -EINVAL;
- goto out;
- }
-
- msg->l2h = msg->data;
- ipa_prepend_header(msg, sign_link->tei);
-
- LOGPITS(e1i_ts, DLMI, LOGL_DEBUG, "TX %u: %s\n", ts_nr,
- osmo_hexdump(msg->l2h, msgb_l2len(msg)));
-
- ret = send(bfd->fd, msg->data, msg->len, 0);
- if (ret != msg->len) {
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "failed to send A-bis IPA signalling "
- "message. Reason: %s\n", strerror(errno));
+ if (res <= 0) {
+ LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "failed reading from socket: %d\n",
res);
goto err;
}
- /* this is some ancient code that apparently exists to slow down writes towards
- * some even more ancient nanoBTS 900 units. See git commit
- * d49fc5ae24fc9d44d2b284392ab619cc7a69a876 of openbsc.git (now osmo-bsc.git) */
- if (e1i_ts->sign.delay) {
- osmo_fd_write_disable(bfd);
- /* set tx delay timer for next event */
- osmo_timer_setup(&e1i_ts->sign.tx_timer, timeout_ts1_write, e1i_ts);
- osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
- } else {
-out:
- if (!e1i_ts_has_pending_tx_msgs(e1i_ts))
- osmo_fd_write_disable(bfd);
+ LOGPITS(e1i_ts, DLMI, LOGL_DEBUG, "RX: %s\n", osmo_hexdump(msgb_l2(msg),
msgb_l2len(msg)));
+
+ if (ipa_proto == IPAC_PROTO_IPACCESS) {
+ ret = ipaccess_bsc_rcvmsg(conn, msg);
+ /* BIG FAT WARNING: bfd might no longer exist here (ret != 0),
+ * since ipaccess_rcvmsg() might have free'd it !!! */
+ return ret != 0 ? -EBADF : 0;
}
- msgb_free(msg);
- return ret;
-err:
- ipaccess_drop(bfd, line);
- msgb_free(msg);
- return ret;
-}
+ if (e1i_ts->type == E1INP_TS_TYPE_NONE) {
+ /* this sign link is not know yet.. complain. */
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Timeslot is not configured.\n");
+ goto err;
+ }
-static int handle_ts1_write(struct osmo_fd *bfd)
-{
- struct e1inp_line *line = bfd->data;
+ link = e1inp_lookup_sign_link(e1i_ts, ipa_proto, 0);
+ if (!link) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "no matching signalling link for
ipa_proto=0x%02x\n", ipa_proto);
+ goto err;
+ }
+ msg->dst = link;
- return __handle_ts1_write(bfd, line);
-}
-
-
-/* callback from select.c in case one of the fd's can be read/written */
-int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what)
-{
- int rc = 0;
-
- if (what & OSMO_FD_READ)
- rc = handle_ts1_read(bfd);
- if (rc != -EBADF && (what & OSMO_FD_WRITE))
- rc = handle_ts1_write(bfd);
+ /* XXX better use e1inp_ts_rx? */
+ if (!e1i_ts->line->ops->sign_link) {
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Fix your application, no action set for
signalling messages.\n");
+ goto err;
+ }
+ rc = e1i_ts->line->ops->sign_link(msg);
+ if (rc < 0) {
+ /* Don't close the signalling link if the upper layers report
+ * an error, that's too strict. BTW, the signalling layer is
+ * resposible for releasing the message.
+ */
+ LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Bad signalling message, sign_link returned
error: %s.\n",
+ strerror(-rc));
+ }
return rc;
+err:
+ msgb_free(msg);
+ osmo_stream_srv_destroy(conn);
+ return 0;
}
-static int ipaccess_line_update(struct e1inp_line *line);
+static int ipaccess_bsc_conn_closed_cb(struct osmo_stream_srv *conn)
+{
+ struct e1inp_ts *e1i_ts = osmo_stream_srv_get_data(conn);
+ struct e1inp_line *line = e1i_ts->line;
+ struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
+ e1inp_line_get2(line, __func__);
+ e1inp_line_put2(line, "ipa_bfd");
-struct e1inp_driver ipaccess_driver = {
- .name = "ipa",
- .want_write = ts_want_write,
- .line_update = ipaccess_line_update,
- .close = ipaccess_close,
- .default_delay = 0,
- .has_keepalive = 1,
-};
+ osmo_stats_tcp_osmo_fd_unregister(bfd);
+ ipaccess_keepalive_fsm_cleanup(e1i_ts);
+
+ osmo_stream_srv_set_data(conn, NULL);
+ bfd->fd = -1;
+ bfd->data = NULL;
+
+ if (line->ops->sign_link_down)
+ line->ops->sign_link_down(line);
+ e1inp_line_put2(line, __func__);
+ return 0;
+}
static void update_fd_settings(struct e1inp_line *line, int fd)
{
@@ -741,16 +657,19 @@
}
/* callback of the OML listening filedescriptor */
-static int ipaccess_bsc_oml_cb(struct ipa_server_link *link, int fd)
+static int ipaccess_bsc_oml_accept_cb(struct osmo_stream_srv_link *link, int fd)
{
int ret;
int i;
+ struct e1inp_line *srv_link_line = osmo_stream_srv_link_get_data(link);
struct e1inp_line *line;
+ struct osmo_stream_srv *conn;
struct e1inp_ts *e1i_ts;
struct osmo_fd *bfd;
+ char conn_name[128];
/* clone virtual E1 line for this new OML link. */
- line = e1inp_line_clone(tall_ipa_ctx, link->line, "ipa_bfd");
+ line = e1inp_line_clone(tall_ipa_ctx, srv_link_line, "ipa_bfd");
if (line == NULL) {
LOGP(DLINP, LOGL_ERROR, "could not clone E1 line\n");
return -ENOMEM;
@@ -765,45 +684,48 @@
e1i_ts = e1inp_line_ipa_oml_ts(line);
+ snprintf(conn_name, sizeof(conn_name), "ts-%u-%u-oml", line->num,
e1i_ts->num);
+ conn = osmo_stream_srv_create2(link, link, fd, e1i_ts);
+ OSMO_ASSERT(conn);
+ osmo_stream_srv_set_name(conn, conn_name);
+ osmo_stream_srv_set_read_cb(conn, ipaccess_bsc_conn_read_cb);
+ osmo_stream_srv_set_closed_cb(conn, ipaccess_bsc_conn_closed_cb);
+ osmo_stream_srv_set_segmentation_cb(conn, osmo_ipa_segmentation_cb);
+
+ /* We use bfd->fd in here for osmo_stats_tcp, and bfd->data to access
osmo_stream_srv from e1i_ts. */
bfd = &e1i_ts->driver.ipaccess.fd;
- osmo_fd_setup(bfd, fd, OSMO_FD_READ, ipaccess_fd_cb, line, E1INP_SIGN_OML);
- ret = osmo_fd_register(bfd);
- if (ret < 0) {
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not register FD\n");
- goto err_line;
- }
+ osmo_fd_setup(bfd, fd, 0, NULL, conn, E1INP_SIGN_OML);
osmo_stats_tcp_osmo_fd_register(bfd, "ipa-oml");
- update_fd_settings(line, bfd->fd);
+ update_fd_settings(line, fd);
/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
- ret = ipa_ccm_send_id_req(bfd->fd);
+ /* PESPIN: TODO: use osmo_stream_srv_send() instead */
+ ret = ipa_ccm_send_id_req(fd);
if (ret < 0) {
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not send ID REQ. Reason: %s\n",
strerror(errno));
goto err_socket;
}
- return ret;
+ return 0;
err_socket:
- osmo_fd_unregister(bfd);
-err_line:
- close(bfd->fd);
- bfd->fd = -1;
- bfd->data = NULL;
- e1inp_line_put2(line, "ipa_bfd");
- return ret;
+ osmo_stream_srv_destroy(conn);
+ return 0;
}
-static int ipaccess_bsc_rsl_cb(struct ipa_server_link *link, int fd)
+static int ipaccess_bsc_rsl_accept_cb(struct osmo_stream_srv_link *link, int fd)
{
+ struct e1inp_line *srv_link_line = osmo_stream_srv_link_get_data(link);
struct e1inp_line *line;
+ struct osmo_stream_srv *conn;
struct e1inp_ts *e1i_ts;
struct osmo_fd *bfd;
int i, ret;
+ char conn_name[128];
/* We don't know yet which OML link to associate it with. Thus, we
* allocate a temporary E1 line until we have received ID. */
- line = e1inp_line_clone(tall_ipa_ctx, link->line, "ipa_bfd");
+ line = e1inp_line_clone(tall_ipa_ctx, srv_link_line, "ipa_bfd");
if (line == NULL) {
LOGP(DLINP, LOGL_ERROR, "could not clone E1 line\n");
return -ENOMEM;
@@ -812,38 +734,38 @@
for (i = 0; i < ARRAY_SIZE(line->ts); ++i)
line->ts[i].driver.ipaccess.fd.fd = -1;
- /* we need this to initialize this in case to avoid crashes in case
+ /* we need to initialize this in case to avoid crashes in case
* that the socket is closed before we've seen an ID_RESP. */
e1inp_ts_config_sign(e1inp_line_ipa_oml_ts(line), line);
e1i_ts = e1inp_line_ipa_rsl_ts(line, 0);
+ snprintf(conn_name, sizeof(conn_name), "ts-%u-%u-rsl", line->num,
e1i_ts->num);
+ conn = osmo_stream_srv_create2(link, link, fd, e1i_ts);
+ OSMO_ASSERT(conn);
+ osmo_stream_srv_set_name(conn, conn_name);
+ osmo_stream_srv_set_read_cb(conn, ipaccess_bsc_conn_read_cb);
+ osmo_stream_srv_set_closed_cb(conn, ipaccess_bsc_conn_closed_cb);
+ osmo_stream_srv_set_segmentation_cb(conn, osmo_ipa_segmentation_cb);
+
+ /* We use bfd->fd in here for osmo_stats_tcp, and bfd->data to access
osmo_stream_srv from e1i_ts. */
bfd = &e1i_ts->driver.ipaccess.fd;
- osmo_fd_setup(bfd, fd, OSMO_FD_READ, ipaccess_fd_cb, line, E1INP_SIGN_RSL);
- ret = osmo_fd_register(bfd);
- if (ret < 0) {
- LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not register FD\n");
- goto err_line;
- }
+ osmo_fd_setup(bfd, fd, 0, NULL, conn, E1INP_SIGN_RSL);
osmo_stats_tcp_osmo_fd_register(bfd, "ipa-rsl");
/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
- ret = ipa_ccm_send_id_req(bfd->fd);
+ /* PESPIN: TODO: use osmo_stream_srv_send() instead */
+ ret = ipa_ccm_send_id_req(fd);
if (ret < 0) {
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "could not send ID REQ. Reason: %s\n",
strerror(errno));
goto err_socket;
}
- update_fd_settings(line, bfd->fd);
- return ret;
+ update_fd_settings(line, fd);
+ return 0;
err_socket:
- osmo_fd_unregister(bfd);
-err_line:
- close(bfd->fd);
- bfd->fd = -1;
- bfd->data = NULL;
- e1inp_line_put2(line, "ipa_bfd");
- return ret;
+ osmo_stream_srv_destroy(conn);
+ return 0;
}
int ipaccess_bts_handle_ccm(struct ipa_client_conn *link,
@@ -1100,38 +1022,43 @@
/* We only initialize this line once. */
if (il->line_already_initialized)
return 0;
- struct ipa_server_link *oml_link, *rsl_link;
+ struct osmo_stream_srv_link *oml_link, *rsl_link;
const char *ipa = e1inp_ipa_get_bind_addr();
LOGPIL(line, DLINP, LOGL_NOTICE, "enabling ipaccess BSC mode on %s "
"with OML %u and RSL %u TCP ports\n", ipa, IPA_TCP_PORT_OML,
IPA_TCP_PORT_RSL);
- oml_link = ipa_server_link_create(tall_ipa_ctx, line, ipa,
- IPA_TCP_PORT_OML,
- ipaccess_bsc_oml_cb, NULL);
- if (oml_link == NULL) {
- LOGPIL(line, DLINP, LOGL_ERROR, "cannot create OML BSC link: %s\n",
strerror(errno));
- return -ENOMEM;
- }
- oml_link->dscp = g_e1inp_ipaccess_pars.oml.dscp;
- oml_link->priority = g_e1inp_ipaccess_pars.oml.priority;
- if (ipa_server_link_open(oml_link) < 0) {
- LOGPIL(line, DLINP, LOGL_ERROR, "cannot open OML BSC link: %s\n",
strerror(errno));
- ipa_server_link_destroy(oml_link);
+ oml_link = osmo_stream_srv_link_create(tall_ipa_ctx);
+ OSMO_ASSERT(oml_link);
+ osmo_stream_srv_link_set_proto(oml_link, IPPROTO_TCP);
+ osmo_stream_srv_link_set_addr(oml_link, ipa);
+ osmo_stream_srv_link_set_port(oml_link, IPA_TCP_PORT_OML);
+ osmo_stream_srv_link_set_data(oml_link, line);
+ osmo_stream_srv_link_set_nodelay(oml_link, true);
+ osmo_stream_srv_link_set_priority(oml_link, g_e1inp_ipaccess_pars.oml.dscp);
+ osmo_stream_srv_link_set_ip_dscp(oml_link, g_e1inp_ipaccess_pars.oml.priority);
+ osmo_stream_srv_link_set_accept_cb(oml_link, ipaccess_bsc_oml_accept_cb);
+
+ if (osmo_stream_srv_link_open(oml_link)) {
+ LOGPIL(line, DLINP, LOGL_ERROR, "cannot open OML BTS link: %s\n",
strerror(errno));
+ osmo_stream_srv_link_destroy(oml_link);
return -EIO;
}
- rsl_link = ipa_server_link_create(tall_ipa_ctx, line, ipa,
- IPA_TCP_PORT_RSL,
- ipaccess_bsc_rsl_cb, NULL);
- if (rsl_link == NULL) {
- LOGPIL(line, DLINP, LOGL_ERROR, "cannot create RSL BSC link: %s\n",
strerror(errno));
- return -ENOMEM;
- }
- rsl_link->dscp = g_e1inp_ipaccess_pars.rsl.dscp;
- rsl_link->priority = g_e1inp_ipaccess_pars.rsl.priority;
- if (ipa_server_link_open(rsl_link) < 0) {
- LOGPIL(line, DLINP, LOGL_ERROR, "cannot open RSL BSC link: %s\n",
strerror(errno));
- ipa_server_link_destroy(rsl_link);
+
+ rsl_link = osmo_stream_srv_link_create(tall_ipa_ctx);
+ OSMO_ASSERT(rsl_link);
+ osmo_stream_srv_link_set_proto(rsl_link, IPPROTO_TCP);
+ osmo_stream_srv_link_set_addr(rsl_link, ipa);
+ osmo_stream_srv_link_set_port(rsl_link, IPA_TCP_PORT_RSL);
+ osmo_stream_srv_link_set_data(rsl_link, line);
+ osmo_stream_srv_link_set_nodelay(rsl_link, true);
+ osmo_stream_srv_link_set_priority(rsl_link, g_e1inp_ipaccess_pars.rsl.dscp);
+ osmo_stream_srv_link_set_ip_dscp(rsl_link, g_e1inp_ipaccess_pars.rsl.priority);
+ osmo_stream_srv_link_set_accept_cb(rsl_link, ipaccess_bsc_rsl_accept_cb);
+
+ if (osmo_stream_srv_link_open(rsl_link)) {
+ LOGPIL(line, DLINP, LOGL_ERROR, "cannot open RSL BTS link: %s\n",
strerror(errno));
+ osmo_stream_srv_link_destroy(rsl_link);
return -EIO;
}
ret = 0;
@@ -1299,6 +1226,15 @@
return 0;
}
+struct e1inp_driver ipaccess_driver = {
+ .name = "ipa",
+ .want_write = ts_want_write,
+ .line_update = ipaccess_line_update,
+ .close = ipaccess_close,
+ .default_delay = 0,
+ .has_keepalive = 1,
+};
+
void e1inp_ipaccess_init(void)
{
tall_ipa_ctx = talloc_named_const(libosmo_abis_ctx, 1, "ipa");
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-abis/+/38983?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: libosmo-abis
Gerrit-Branch: master
Gerrit-Change-Id: Idf241c8f2fdb86d090d4132a9b316b7236402232
Gerrit-Change-Number: 38983
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>