summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso2011-07-08 16:21:55 +0200
committerPablo Neira Ayuso2011-07-08 16:21:55 +0200
commit88136fc6dd4c432e13193c9e29c4bea927141812 (patch)
tree4bb8372b765223af9cd89e436a5d167a1fdd3c16
parenttests: close OML and RSL if set for the BSC example (diff)
downloadlibosmo-abis-88136fc6dd4c432e13193c9e29c4bea927141812.tar.gz
libosmo-abis-88136fc6dd4c432e13193c9e29c4bea927141812.tar.xz
libosmo-abis-88136fc6dd4c432e13193c9e29c4bea927141812.zip
hsl: BTS support
This patch adds the BTS support for the hsl driver. It includes two examples under the tests/ directory.
-rw-r--r--include/internal.h4
-rw-r--r--include/osmocom/abis/ipa.h3
-rw-r--r--include/osmocom/abis/ipaccess.h3
-rw-r--r--src/input/hsl.c116
-rw-r--r--src/input/ipa.c27
-rw-r--r--src/input/ipaccess.c34
-rw-r--r--src/ipa_proxy.c1
-rw-r--r--tests/Makefile.am10
8 files changed, 157 insertions, 41 deletions
diff --git a/include/internal.h b/include/internal.h
index a1356ad..6969748 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -1,6 +1,8 @@
#ifndef _INTERNAL_H_
#define _INTERNAL_H_
+#include <stdint.h>
+
/* talloc context for libosmo-abis. */
extern void *libosmo_abis_ctx;
@@ -10,5 +12,7 @@ void e1inp_init(void);
/* hsl requires these functions defined in ipaccess driver. */
struct msgb;
void ipaccess_prepend_header(struct msgb *msg, int proto);
+struct msgb *ipa_msg_alloc(int headroom);
+void ipa_msg_push_header(struct msgb *msg, uint8_t proto);
#endif
diff --git a/include/osmocom/abis/ipa.h b/include/osmocom/abis/ipa.h
index d455069..2254629 100644
--- a/include/osmocom/abis/ipa.h
+++ b/include/osmocom/abis/ipa.h
@@ -48,12 +48,13 @@ struct ipa_client_link {
enum ipa_client_link_state state;
const char *addr;
uint16_t port;
+ int (*connect_cb)(struct ipa_client_link *link);
int (*read_cb)(struct ipa_client_link *link, struct msgb *msg);
int (*write_cb)(struct ipa_client_link *link);
void *data;
};
-struct ipa_client_link *ipa_client_link_create(void *ctx, struct e1inp_ts *ts, const char *driver_name, int priv_nr, const char *addr, uint16_t port, int (*read_cb)(struct ipa_client_link *link, struct msgb *msgb), int (*write_cb)(struct ipa_client_link *link), void *data);
+struct ipa_client_link *ipa_client_link_create(void *ctx, struct e1inp_ts *ts, const char *driver_name, int priv_nr, const char *addr, uint16_t port, int (*connect)(struct ipa_client_link *link), int (*read_cb)(struct ipa_client_link *link, struct msgb *msgb), int (*write_cb)(struct ipa_client_link *link), void *data);
void ipa_client_link_destroy(struct ipa_client_link *link);
int ipa_client_write_default_cb(struct ipa_client_link *link);
diff --git a/include/osmocom/abis/ipaccess.h b/include/osmocom/abis/ipaccess.h
index 6816d87..7083ce9 100644
--- a/include/osmocom/abis/ipaccess.h
+++ b/include/osmocom/abis/ipaccess.h
@@ -104,7 +104,8 @@ struct ipaccess_unit {
};
struct hsl_unit {
- unsigned long serno;
+ uint8_t swversion;
+ uint64_t serno;
};
#endif /* _OSMO_PROTO_IPACCESS_H */
diff --git a/src/input/hsl.c b/src/input/hsl.c
index 36061f5..7058f48 100644
--- a/src/input/hsl.c
+++ b/src/input/hsl.c
@@ -76,6 +76,15 @@ static struct hsl_e1_handle *e1h;
static void hsl_drop(struct e1inp_line *line, struct osmo_fd *bfd)
{
line->ops->sign_link_down(line);
+
+ if (bfd->fd != -1) {
+ osmo_fd_unregister(bfd);
+ close(bfd->fd);
+ bfd->fd = -1;
+ }
+ /* put the virtual E1 line that we cloned for this socket, if
+ * it becomes unused, it gets released. */
+ e1inp_line_put(line);
}
static int process_hsl_rsl(struct msgb *msg, struct e1inp_line *line,
@@ -205,9 +214,8 @@ static void timeout_ts1_write(void *data)
ts_want_write(e1i_ts);
}
-static int handle_ts1_write(struct osmo_fd *bfd)
+static int __handle_ts1_write(struct osmo_fd *bfd, struct e1inp_line *line)
{
- struct e1inp_line *line = bfd->data;
unsigned int ts_nr = bfd->priv_nr;
struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
struct e1inp_sign_link *sign_link;
@@ -260,6 +268,20 @@ static int handle_ts1_write(struct osmo_fd *bfd)
return ret;
}
+static int handle_ts1_write(struct osmo_fd *bfd)
+{
+ struct e1inp_line *line = bfd->data;
+
+ return __handle_ts1_write(bfd, line);
+}
+
+int hsl_bts_write(struct ipa_client_link *link)
+{
+ struct e1inp_line *line = link->line;
+
+ return __handle_ts1_write(link->ofd, line);
+}
+
/* callback from select.c in case one of the fd's can be read/written */
static int hsl_fd_cb(struct osmo_fd *bfd, unsigned int what)
{
@@ -301,7 +323,7 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
int ret;
int idx = 0;
int i;
- struct e1inp_line *line = listen_bfd->data;
+ struct e1inp_line *line;
struct e1inp_ts *e1i_ts;
struct osmo_fd *bfd;
struct sockaddr_in sa;
@@ -318,6 +340,12 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
LOGP(DINP, LOGL_NOTICE, "accept()ed new HSL link from %s\n",
inet_ntoa(sa.sin_addr));
+ /* clone virtual E1 line for this new signalling link. */
+ line = e1inp_line_clone(tall_hsl_ctx, listen_bfd->data);
+ if (line == NULL) {
+ LOGP(DINP, LOGL_ERROR, "could not clone E1 line\n");
+ return -1;
+ }
/* create virrtual E1 timeslots for signalling */
e1inp_ts_config_sign(&line->ts[1-1], line);
@@ -337,7 +365,7 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
if (ret < 0) {
LOGP(DINP, LOGL_ERROR, "could not register FD\n");
close(bfd->fd);
- talloc_free(line);
+ e1inp_line_put(line);
return ret;
}
@@ -346,7 +374,74 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
static int hsl_bts_process(struct ipa_client_link *link, struct msgb *msg)
{
- /* XXX: not implemented yet. */
+ struct ipaccess_head *hh;
+ struct e1inp_sign_link *sign_link;
+ struct e1inp_ts *e1i_ts = &link->line->ts[0];
+
+ hh = (struct ipaccess_head *) msg->data;
+ if (hh->proto == HSL_PROTO_DEBUG) {
+ LOGP(DINP, LOGL_NOTICE, "HSL debug: %s\n",
+ msg->data + sizeof(*hh));
+ msgb_free(msg);
+ return 0;
+ }
+ sign_link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0);
+ if (!sign_link) {
+ LOGP(DINP, LOGL_ERROR, "no matching signalling link for "
+ "hh->proto=0x%02x\n", hh->proto);
+ msgb_free(msg);
+ return -EIO;
+ }
+ msg->dst = sign_link;
+
+ /* XXX better use e1inp_ts_rx? */
+ if (!link->line->ops->sign_link) {
+ LOGP(DINP, LOGL_ERROR, "Fix your application, "
+ "no action set for signalling messages.\n");
+ return -ENOENT;
+ }
+ link->line->ops->sign_link(msg);
+ return 0;
+}
+
+static int hsl_bts_connect(struct ipa_client_link *link)
+{
+ struct msgb *msg;
+ uint8_t *serno;
+ char serno_buf[16];
+ struct hsl_unit *unit = link->line->ops->data;
+ struct e1inp_sign_link *sign_link;
+
+ /* send the minimal message to identify this BTS. */
+ msg = ipa_msg_alloc(0);
+ if (!msg)
+ return -ENOMEM;
+
+ *msgb_put(msg, 1) = 0x80;
+ *msgb_put(msg, 1) = 0x80;
+ *msgb_put(msg, 1) = unit->swversion;
+ snprintf(serno_buf, sizeof(serno_buf), "%llx", unit->serno);
+ serno = msgb_put(msg, strlen(serno_buf)+1);
+ memcpy(serno, serno_buf, strlen(serno_buf));
+ ipa_msg_push_header(msg, 0);
+ send(link->ofd->fd, msg->data, msg->len, 0);
+ msgb_free(msg);
+
+ /* ... and enable the signalling link. */
+ if (!link->line->ops->sign_link_up) {
+ LOGP(DINP, LOGL_ERROR,
+ "Unable to set signal link, closing socket.\n");
+ ipa_client_link_close(link);
+ return -EINVAL;
+ }
+ sign_link = link->line->ops->sign_link_up(&unit,
+ link->line, E1INP_SIGN_NONE);
+ if (sign_link == NULL) {
+ LOGP(DINP, LOGL_ERROR,
+ "Unable to set signal link, closing socket.\n");
+ ipa_client_link_close(link);
+ return -EINVAL;
+ }
return 0;
}
@@ -380,10 +475,13 @@ static int hsl_line_update(struct e1inp_line *line,
LOGP(DINP, LOGL_NOTICE, "enabling hsl BTS mode\n");
link = ipa_client_link_create(tall_hsl_ctx,
- &line->ts[0], "hsl", 0,
- addr, HSL_TCP_PORT,
- hsl_bts_process, NULL,
- NULL);
+ &line->ts[E1INP_SIGN_OML-1],
+ "hsl", E1INP_SIGN_OML,
+ addr, HSL_TCP_PORT,
+ hsl_bts_connect,
+ hsl_bts_process,
+ hsl_bts_write,
+ NULL);
if (link == NULL) {
LOGP(DINP, LOGL_ERROR, "cannot create BTS link: %s\n",
strerror(errno));
diff --git a/src/input/ipa.c b/src/input/ipa.c
index c65a0ec..c8ee781 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -24,9 +24,26 @@
#define IPA_ALLOC_SIZE 1200
-static struct msgb *ipa_msg_alloc(void)
+struct msgb *ipa_msg_alloc(int headroom)
{
- return msgb_alloc(IPA_ALLOC_SIZE, "Abis/IP");
+ struct msgb *nmsg;
+
+ headroom += sizeof(struct ipaccess_head);
+
+ nmsg = msgb_alloc_headroom(1200 + headroom, headroom, "Abis/IP");
+ if (!nmsg)
+ return NULL;
+ return nmsg;
+}
+
+void ipa_msg_push_header(struct msgb *msg, uint8_t proto)
+{
+ struct ipaccess_head *hh;
+
+ msg->l2h = msg->data;
+ hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
+ hh->proto = proto;
+ hh->len = htons(msgb_l2len(msg));
}
int ipa_msg_recv(int fd, struct msgb **rmsg)
@@ -35,7 +52,7 @@ int ipa_msg_recv(int fd, struct msgb **rmsg)
struct ipaccess_head *hh;
int len, ret;
- msg = ipa_msg_alloc();
+ msg = ipa_msg_alloc(0);
if (msg == NULL)
return -ENOMEM;
@@ -166,6 +183,8 @@ int ipa_client_fd_cb(struct osmo_fd *ofd, unsigned int what)
ofd->when &= ~BSC_FD_WRITE;
LOGP(DINP, LOGL_NOTICE, "connection done.\n");
link->state = IPA_CLIENT_LINK_STATE_CONNECTED;
+ if (link->connect_cb)
+ link->connect_cb(link);
break;
case IPA_CLIENT_LINK_STATE_CONNECTED:
if (what & BSC_FD_READ) {
@@ -188,6 +207,7 @@ static void ipa_link_timer_cb(void *data);
struct ipa_client_link *
ipa_client_link_create(void *ctx, struct e1inp_ts *ts, const char *driver_name,
int priv_nr, const char *addr, uint16_t port,
+ int (*connect_cb)(struct ipa_client_link *link),
int (*read_cb)(struct ipa_client_link *link,
struct msgb *msgb),
int (*write_cb)(struct ipa_client_link *link),
@@ -226,6 +246,7 @@ ipa_client_link_create(void *ctx, struct e1inp_ts *ts, const char *driver_name,
ipa_link->timer.data = ipa_link;
ipa_link->addr = talloc_strdup(ipa_link, addr);
ipa_link->port = port;
+ ipa_link->connect_cb = connect_cb;
ipa_link->read_cb = read_cb;
ipa_link->write_cb = write_cb;
ipa_link->line = ts->line;
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index 2acac89..1864683 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -528,7 +528,7 @@ static int __handle_ts1_write(struct osmo_fd *bfd, struct e1inp_line *line)
return ret;
}
-int handle_ts1_write(struct osmo_fd *bfd)
+static int handle_ts1_write(struct osmo_fd *bfd)
{
struct e1inp_line *line = bfd->data;
@@ -655,28 +655,6 @@ static int ipaccess_bsc_rsl_cb(struct ipa_server_link *link, int fd)
return 0;
}
-static struct msgb *abis_msgb_alloc(int headroom)
-{
- struct msgb *nmsg;
-
- headroom += sizeof(struct ipaccess_head);
-
- nmsg = msgb_alloc_headroom(1200 + headroom, headroom, "dummy BTS");
- if (!nmsg)
- return NULL;
- return nmsg;
-}
-
-static void abis_push_ipa(struct msgb *msg, uint8_t proto)
-{
- struct ipaccess_head *nhh;
-
- msg->l2h = msg->data;
- nhh = (struct ipaccess_head *) msgb_push(msg, sizeof(*nhh));
- nhh->proto = proto;
- nhh->len = htons(msgb_l2len(msg));
-}
-
static struct msgb *
ipa_bts_id_resp(struct ipaccess_unit *dev, uint8_t *data, int len)
{
@@ -684,7 +662,7 @@ ipa_bts_id_resp(struct ipaccess_unit *dev, uint8_t *data, int len)
char str[64];
uint8_t *tag;
- nmsg = abis_msgb_alloc(0);
+ nmsg = ipa_msg_alloc(0);
if (!nmsg)
return NULL;
@@ -744,7 +722,7 @@ ipa_bts_id_resp(struct ipaccess_unit *dev, uint8_t *data, int len)
data += 2;
len -= 2;
}
- abis_push_ipa(nmsg, IPAC_PROTO_IPACCESS);
+ ipa_msg_push_header(nmsg, IPAC_PROTO_IPACCESS);
return nmsg;
}
@@ -752,12 +730,12 @@ static struct msgb *ipa_bts_id_ack(void)
{
struct msgb *nmsg2;
- nmsg2 = abis_msgb_alloc(0);
+ nmsg2 = ipa_msg_alloc(0);
if (!nmsg2)
return NULL;
*msgb_put(nmsg2, 1) = IPAC_MSGT_ID_ACK;
- abis_push_ipa(nmsg2, IPAC_PROTO_IPACCESS);
+ ipa_msg_push_header(nmsg2, IPAC_PROTO_IPACCESS);
return nmsg2;
}
@@ -893,6 +871,7 @@ static int ipaccess_line_update(struct e1inp_line *line,
&line->ts[E1INP_SIGN_OML-1],
"ipa", E1INP_SIGN_OML,
addr, IPA_TCP_PORT_OML,
+ NULL,
ipaccess_bts_cb,
ipaccess_bts_write_cb,
NULL);
@@ -912,6 +891,7 @@ static int ipaccess_line_update(struct e1inp_line *line,
&line->ts[E1INP_SIGN_RSL-1],
"ipa", E1INP_SIGN_RSL,
addr, IPA_TCP_PORT_RSL,
+ NULL,
ipaccess_bts_cb,
ipaccess_bts_write_cb,
NULL);
diff --git a/src/ipa_proxy.c b/src/ipa_proxy.c
index 2ad4654..c79b544 100644
--- a/src/ipa_proxy.c
+++ b/src/ipa_proxy.c
@@ -188,6 +188,7 @@ ipa_sock_src_accept_cb(struct ipa_server_link *link, int fd)
conn->dst = ipa_client_link_create(NULL, NULL, NULL, 0,
route->shared->dst.inst->net.addr,
route->shared->dst.inst->net.port,
+ NULL,
ipa_sock_dst_cb,
ipa_client_write_default_cb,
conn);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5cb6447..26500a1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,6 +4,8 @@ AM_LDFLAGS = $(COVERAGE_LDFLAGS)
noinst_PROGRAMS = e1inp_ipa_bsc_test \
e1inp_ipa_bts_test \
+ e1inp_hsl_bsc_test \
+ e1inp_hsl_bts_test \
ipa_proxy_test
e1inp_ipa_bsc_test_SOURCES = e1inp_ipa_bsc_test.c
@@ -14,6 +16,14 @@ e1inp_ipa_bts_test_SOURCES = e1inp_ipa_bts_test.c
e1inp_ipa_bts_test_LDADD = $(top_builddir)/src/libosmoabis.la \
$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
+e1inp_hsl_bsc_test_SOURCES = e1inp_hsl_bsc_test.c
+e1inp_hsl_bsc_test_LDADD = $(top_builddir)/src/libosmoabis.la \
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
+
+e1inp_hsl_bts_test_SOURCES = e1inp_hsl_bts_test.c
+e1inp_hsl_bts_test_LDADD = $(top_builddir)/src/libosmoabis.la \
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
+
ipa_proxy_test_SOURCES = ipa_proxy_test.c
ipa_proxy_test_LDADD = $(top_builddir)/src/libosmoabis.la \
$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)