From 88136fc6dd4c432e13193c9e29c4bea927141812 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 8 Jul 2011 16:21:55 +0200 Subject: hsl: BTS support This patch adds the BTS support for the hsl driver. It includes two examples under the tests/ directory. --- include/internal.h | 4 ++ include/osmocom/abis/ipa.h | 3 +- include/osmocom/abis/ipaccess.h | 3 +- src/input/hsl.c | 116 ++++++++++++++++++++++++++++++++++++---- src/input/ipa.c | 27 ++++++++-- src/input/ipaccess.c | 34 +++--------- src/ipa_proxy.c | 1 + tests/Makefile.am | 10 ++++ 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 + /* 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) -- cgit v1.2.3-55-g7522