From 6529701da89b0ed0df9c0ff8c4a2535dd55046ce Mon Sep 17 00:00:00 2001 From: "Andreas.Eversberg" Date: Sat, 11 Sep 2010 10:42:29 +0000 Subject: [layer23] Added BTSAP socket interface to layer23 --- .../layer23/include/osmocom/bb/common/logging.h | 1 + .../include/osmocom/bb/common/osmocom_data.h | 9 +- .../include/osmocom/bb/common/sap_interface.h | 11 ++ src/host/layer23/src/common/Makefile.am | 3 +- src/host/layer23/src/common/l1l2_interface.c | 28 ++-- src/host/layer23/src/common/logging.c | 6 + src/host/layer23/src/common/main.c | 22 ++- src/host/layer23/src/common/sap_interface.c | 183 +++++++++++++++++++++ 8 files changed, 242 insertions(+), 21 deletions(-) create mode 100644 src/host/layer23/include/osmocom/bb/common/sap_interface.h create mode 100644 src/host/layer23/src/common/sap_interface.c diff --git a/src/host/layer23/include/osmocom/bb/common/logging.h b/src/host/layer23/include/osmocom/bb/common/logging.h index 1a11cf9d..ddb449af 100644 --- a/src/host/layer23/include/osmocom/bb/common/logging.h +++ b/src/host/layer23/include/osmocom/bb/common/logging.h @@ -17,6 +17,7 @@ enum { DPAG, DLAPDM, DL1C, + DSAP, DSUM, }; diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h index 2fa59f7b..4d5fdf8d 100644 --- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h +++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h @@ -12,6 +12,7 @@ struct osmocom_ms; #include #include #include +#include #include #include #include @@ -25,6 +26,10 @@ struct osmol2_entity { osmol2_cb_t msg_handler; }; +struct osmosap_entity { + osmosap_cb_t msg_handler; +}; + /* RX measurement statistics */ struct rx_meas_stat { uint32_t last_fn; @@ -38,7 +43,7 @@ struct rx_meas_stat { struct osmocom_ms { struct llist_head entity; char name[32]; - struct write_queue wq; + struct write_queue l2_wq, sap_wq; uint16_t test_arfcn; struct gsm_support support; @@ -49,6 +54,8 @@ struct osmocom_ms { struct osmol2_entity l2_entity; + struct osmosap_entity sap_entity; + struct rx_meas_stat meas; struct gsm48_rrlayer rrlayer; diff --git a/src/host/layer23/include/osmocom/bb/common/sap_interface.h b/src/host/layer23/include/osmocom/bb/common/sap_interface.h new file mode 100644 index 00000000..f2f577a7 --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/common/sap_interface.h @@ -0,0 +1,11 @@ +#ifndef _SAP_INTERFACE_H +#define _SAP_INTERFACE_H + +typedef int (*osmosap_cb_t)(struct msgb *msg, struct osmocom_ms *ms); + +int sap_open(struct osmocom_ms *ms, const char *socket_path); +int sap_close(struct osmocom_ms *ms); +int osmosap_send(struct osmocom_ms *ms, struct msgb *msg); +int osmosap_register_handler(struct osmocom_ms *ms, osmosap_cb_t cb); + +#endif /* _SAP_INTERFACE_H */ diff --git a/src/host/layer23/src/common/Makefile.am b/src/host/layer23/src/common/Makefile.am index 5c0d41bb..1dadb513 100644 --- a/src/host/layer23/src/common/Makefile.am +++ b/src/host/layer23/src/common/Makefile.am @@ -2,4 +2,5 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) noinst_LIBRARIES = liblayer23.a -liblayer23_a_SOURCES = l1ctl.c l1l2_interface.c lapdm.c logging.c networks.c +liblayer23_a_SOURCES = l1ctl.c l1l2_interface.c sap_interface.c lapdm.c \ + logging.c networks.c diff --git a/src/host/layer23/src/common/l1l2_interface.c b/src/host/layer23/src/common/l1l2_interface.c index 2061adb3..2298921c 100644 --- a/src/host/layer23/src/common/l1l2_interface.c +++ b/src/host/layer23/src/common/l1l2_interface.c @@ -102,31 +102,31 @@ int layer2_open(struct osmocom_ms *ms, const char *socket_path) int rc; struct sockaddr_un local; - ms->wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (ms->wq.bfd.fd < 0) { + ms->l2_wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (ms->l2_wq.bfd.fd < 0) { fprintf(stderr, "Failed to create unix domain socket.\n"); - return ms->wq.bfd.fd; + return ms->l2_wq.bfd.fd; } local.sun_family = AF_UNIX; strncpy(local.sun_path, socket_path, sizeof(local.sun_path)); local.sun_path[sizeof(local.sun_path) - 1] = '\0'; - rc = connect(ms->wq.bfd.fd, (struct sockaddr *) &local, + rc = connect(ms->l2_wq.bfd.fd, (struct sockaddr *) &local, sizeof(local.sun_family) + strlen(local.sun_path)); if (rc < 0) { fprintf(stderr, "Failed to connect to '%s'.\n", local.sun_path); - close(ms->wq.bfd.fd); + close(ms->l2_wq.bfd.fd); return rc; } - write_queue_init(&ms->wq, 100); - ms->wq.bfd.data = ms; - ms->wq.bfd.when = BSC_FD_READ; - ms->wq.read_cb = layer2_read; - ms->wq.write_cb = layer2_write; + write_queue_init(&ms->l2_wq, 100); + ms->l2_wq.bfd.data = ms; + ms->l2_wq.bfd.when = BSC_FD_READ; + ms->l2_wq.read_cb = layer2_read; + ms->l2_wq.write_cb = layer2_write; - rc = bsc_register_fd(&ms->wq.bfd); + rc = bsc_register_fd(&ms->l2_wq.bfd); if (rc != 0) { fprintf(stderr, "Failed to register fd.\n"); return rc; @@ -137,8 +137,8 @@ int layer2_open(struct osmocom_ms *ms, const char *socket_path) int layer2_close(struct osmocom_ms *ms) { - close(ms->wq.bfd.fd); - bsc_unregister_fd(&ms->wq.bfd); + close(ms->l2_wq.bfd.fd); + bsc_unregister_fd(&ms->l2_wq.bfd); return 0; } @@ -156,7 +156,7 @@ int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg) len = (uint16_t *) msgb_push(msg, sizeof(*len)); *len = htons(msg->len - sizeof(*len)); - if (write_queue_enqueue(&ms->wq, msg) != 0) { + if (write_queue_enqueue(&ms->l2_wq, msg) != 0) { LOGP(DL1C, LOGL_ERROR, "Failed to enqueue msg.\n"); msgb_free(msg); return -1; diff --git a/src/host/layer23/src/common/logging.c b/src/host/layer23/src/common/logging.c index 281f46fb..ecb482c4 100644 --- a/src/host/layer23/src/common/logging.c +++ b/src/host/layer23/src/common/logging.c @@ -96,6 +96,12 @@ static const struct log_info_cat default_categories[] = { .color = "\033[1;31m", .enabled = 1, .loglevel = LOGL_DEBUG, }, + [DSAP] = { + .name = "DSAP", + .description = "SAP Control", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, [DSUM] = { .name = "DSUM", .description = "Summary of Process", diff --git a/src/host/layer23/src/common/main.c b/src/host/layer23/src/common/main.c index 4bf14d08..ba16a321 100644 --- a/src/host/layer23/src/common/main.c +++ b/src/host/layer23/src/common/main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,8 @@ struct log_target *stderr_target; void *l23_ctx = NULL; -static char *socket_path = "/tmp/osmocom_l2"; +static char *layer2_socket_path = "/tmp/osmocom_l2"; +static char *sap_socket_path = "/tmp/osmocom_sap"; struct llist_head ms_list; static struct osmocom_ms *ms = NULL; static uint32_t gsmtap_ip = 0; @@ -75,7 +77,9 @@ static void print_help() printf(" Some help...\n"); printf(" -h --help this text\n"); printf(" -s --socket /tmp/osmocom_l2. Path to the unix " - "domain socket\n"); + "domain socket (l2)\n"); + printf(" -S --sap /tmp/osmocom_sap. Path to the unix " + "domain socket (BTSAP)\n"); printf(" -a --arfcn NR The ARFCN to be used for layer2.\n"); printf(" -i --gsmtap-ip The destination IP used for GSMTAP.\n"); printf(" -v --vty-port The VTY port number to telnet to. " @@ -91,6 +95,7 @@ static void handle_options(int argc, char **argv) static struct option long_options[] = { {"help", 0, 0, 'h'}, {"socket", 1, 0, 's'}, + {"sap", 1, 0, 'S'}, {"arfcn", 1, 0, 'a'}, {"gsmtap-ip", 1, 0, 'i'}, {"vty-port", 1, 0, 'v'}, @@ -98,7 +103,7 @@ static void handle_options(int argc, char **argv) {0, 0, 0, 0}, }; - c = getopt_long(argc, argv, "hs:a:i:v:d:", + c = getopt_long(argc, argv, "hs:S:a:i:v:d:", long_options, &option_index); if (c == -1) break; @@ -110,7 +115,10 @@ static void handle_options(int argc, char **argv) exit(0); break; case 's': - socket_path = talloc_strdup(l23_ctx, optarg); + layer2_socket_path = talloc_strdup(l23_ctx, optarg); + break; + case 'S': + sap_socket_path = talloc_strdup(l23_ctx, optarg); break; case 'a': ms->test_arfcn = atoi(optarg); @@ -176,12 +184,16 @@ int main(int argc, char **argv) handle_options(argc, argv); - rc = layer2_open(ms, socket_path); + rc = layer2_open(ms, layer2_socket_path); if (rc < 0) { fprintf(stderr, "Failed during layer2_open()\n"); exit(1); } + rc = sap_open(ms, sap_socket_path); + if (rc < 0) + fprintf(stderr, "Failed during sap_open(), no SIM reader\n"); + lapdm_init(&ms->l2_entity.lapdm_dcch, ms); lapdm_init(&ms->l2_entity.lapdm_acch, ms); diff --git a/src/host/layer23/src/common/sap_interface.c b/src/host/layer23/src/common/sap_interface.c new file mode 100644 index 00000000..13e30097 --- /dev/null +++ b/src/host/layer23/src/common/sap_interface.c @@ -0,0 +1,183 @@ +/* BTSAP socket interface of layer2/3 stack */ + +/* (C) 2010 by Holger Hans Peter Freyther + * (C) 2010 by Harald Welte + * (C) 2010 by Andreas Eversberg + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include +#include + +#include + +#define _GNU_SOURCE +#include +#include +#include +#include + +#define GSM_SAP_LENGTH 300 +#define GSM_SAP_HEADROOM 32 + +extern int quit; + +static int sap_read(struct bsc_fd *fd) +{ + struct msgb *msg; + u_int16_t len; + int rc; + struct osmocom_ms *ms = (struct osmocom_ms *) fd->data; + + msg = msgb_alloc_headroom(GSM_SAP_LENGTH+GSM_SAP_HEADROOM, GSM_SAP_HEADROOM, "Layer2"); + if (!msg) { + LOGP(DSAP, LOGL_ERROR, "Failed to allocate msg.\n"); + return -ENOMEM; + } + + rc = read(fd->fd, &len, sizeof(len)); + if (rc < sizeof(len)) { + fprintf(stderr, "SAP socket failed\n"); + if (rc >= 0) + rc = -EIO; + quit = rc; + return rc; + } + + len = ntohs(len); + if (len > GSM_SAP_LENGTH) { + LOGP(DSAP, LOGL_ERROR, "Length is too big: %u\n", len); + msgb_free(msg); + return -EINVAL; + } + + + msg->l1h = msgb_put(msg, len); + rc = read(fd->fd, msg->l1h, msgb_l1len(msg)); + if (rc != msgb_l1len(msg)) { + LOGP(DSAP, LOGL_ERROR, "Can not read data: len=%d rc=%d " + "errno=%d\n", len, rc, errno); + msgb_free(msg); + return rc; + } + + if (ms->sap_entity.msg_handler) + ms->sap_entity.msg_handler(msg, ms); + + return 0; +} + +static int sap_write(struct bsc_fd *fd, struct msgb *msg) +{ + int rc; + + rc = write(fd->fd, msg->data, msg->len); + if (rc != msg->len) { + LOGP(DSAP, LOGL_ERROR, "Failed to write data: rc: %d\n", rc); + return rc; + } + + return 0; +} + +int sap_open(struct osmocom_ms *ms, const char *socket_path) +{ + int rc; + struct sockaddr_un local; + + ms->sap_wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (ms->sap_wq.bfd.fd < 0) { + fprintf(stderr, "Failed to create unix domain socket.\n"); + return ms->sap_wq.bfd.fd; + } + + local.sun_family = AF_UNIX; + strncpy(local.sun_path, socket_path, sizeof(local.sun_path)); + local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + + rc = connect(ms->sap_wq.bfd.fd, (struct sockaddr *) &local, + sizeof(local.sun_family) + strlen(local.sun_path)); + if (rc < 0) { + fprintf(stderr, "Failed to connect to '%s'.\n", local.sun_path); + close(ms->sap_wq.bfd.fd); + return rc; + } + + write_queue_init(&ms->sap_wq, 100); + ms->sap_wq.bfd.data = ms; + ms->sap_wq.bfd.when = BSC_FD_READ; + ms->sap_wq.read_cb = sap_read; + ms->sap_wq.write_cb = sap_write; + + rc = bsc_register_fd(&ms->sap_wq.bfd); + if (rc != 0) { + fprintf(stderr, "Failed to register fd.\n"); + return rc; + } + + return 0; +} + +int sap_close(struct osmocom_ms *ms) +{ + if (ms->sap_wq.bfd.fd <= 0) + return -EINVAL; + + close(ms->sap_wq.bfd.fd); + bsc_unregister_fd(&ms->sap_wq.bfd); + + return 0; +} + +int osmosap_send(struct osmocom_ms *ms, struct msgb *msg) +{ + uint16_t *len; + + if (ms->sap_wq.bfd.fd <= 0) + return -EINVAL; + + DEBUGP(DSAP, "Sending: '%s'\n", hexdump(msg->data, msg->len)); + + if (msg->l1h != msg->data) + LOGP(DSAP, LOGL_ERROR, "Message SAP header != Message Data\n"); + + /* prepend 16bit length before sending */ + len = (uint16_t *) msgb_push(msg, sizeof(*len)); + *len = htons(msg->len - sizeof(*len)); + + if (write_queue_enqueue(&ms->sap_wq, msg) != 0) { + LOGP(DSAP, LOGL_ERROR, "Failed to enqueue msg.\n"); + msgb_free(msg); + return -1; + } + + return 0; +} + +/* register message handler for messages that are sent from L2->L3 */ +int osmosap_register_handler(struct osmocom_ms *ms, osmosap_cb_t cb) +{ + ms->sap_entity.msg_handler = cb; + + return 0; +} + -- cgit v1.2.3