diff options
author | Ivan Kluchnikov <kluchnikovi@gmail.com> | 2012-07-12 14:49:15 +0400 |
---|---|---|
committer | Ivan Kluchnikov <kluchnikovi@gmail.com> | 2012-07-12 14:49:15 +0400 |
commit | ef7f28cc7fe67e353821c5f88bc80d5120fec3ca (patch) | |
tree | ca1b24fafa82862b1d5cd38ce1434973033588f0 /src/openbts_sock.cpp | |
parent | c7e7f6868b6f24346424dee904f4e76d3f216ff4 (diff) | |
parent | e13fa2d56936d6bed8febcc41508a30e4a1038f0 (diff) |
Merge branch 'jolly_new'
Merge is based on jolly_new branch with two modifications.
1. Modified PCU L1 interface.
pcu_l1_if.cpp - common functions for tx and rx messages on L1 interface.
sysmo_sock.cpp - SYSMO-PCU socket functions.
openbts_sock.cpp - OpenBTS-PCU socket functions.
pcuif_proto.h - L1 interface's primitives.
2. Modified encoding of RLC/MAC Control messages, now we use structures and encode_gsm_rlcmac_downlink() function for encode control blocks (without hand-coding).
Diffstat (limited to 'src/openbts_sock.cpp')
-rw-r--r-- | src/openbts_sock.cpp | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/openbts_sock.cpp b/src/openbts_sock.cpp new file mode 100644 index 00000000..cbf7adcc --- /dev/null +++ b/src/openbts_sock.cpp @@ -0,0 +1,183 @@ +/* openbts_sock.cpp + * + * Copyright (C) 2012 Ivan Klyuchnikov + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <errno.h> +#include <string.h> +#include <gprs_rlcmac.h> +#include <gprs_bssgp_pcu.h> +#include <pcu_l1_if.h> +#include <gprs_debug.h> +#include <bitvector.h> +#include <sys/socket.h> +#include <arpa/inet.h> +extern "C" { +#include <osmocom/core/talloc.h> +#include <osmocom/core/write_queue.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/timer.h> +#include <osmocom/gsm/gsm_utils.h> +#include <pcuif_proto.h> +} + +struct femtol1_hdl { + struct gsm_time gsm_time; + uint32_t hLayer1; /* handle to the L1 instance in the DSP */ + uint32_t dsp_trace_f; + uint16_t clk_cal; + struct llist_head wlc_list; + + void *priv; /* user reference */ + + struct osmo_timer_list alive_timer; + unsigned int alive_prim_cnt; + + struct osmo_fd read_ofd; /* osmo file descriptors */ + struct osmo_wqueue write_q; + + struct { + uint16_t arfcn; + uint8_t tn; + uint8_t tsc; + uint16_t ta; + } channel_info; + +}; + +struct l1fwd_hdl { + struct sockaddr_storage remote_sa; + socklen_t remote_sa_len; + + struct osmo_wqueue udp_wq; + + struct femtol1_hdl *fl1h; +}; + +struct l1fwd_hdl *l1fh = talloc_zero(NULL, struct l1fwd_hdl); + +// TODO: We should move this parameters to config file. +#define PCU_L1_IF_PORT 5944 + +/* OpenBTS socket functions */ + +int pcu_sock_send(struct msgb *msg) +{ + osmo_wqueue_enqueue(&l1fh->udp_wq, msg); + return 0; +} + +/* data has arrived on the udp socket */ +static int udp_read_cb(struct osmo_fd *ofd) +{ + struct msgb *msg = msgb_alloc_headroom(2048, 128, "udp_rx"); + struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data; + struct femtol1_hdl *fl1h = l1fh->fl1h; + int rc; + + if (!msg) + return -ENOMEM; + + msg->l1h = msg->data; + + l1fh->remote_sa_len = sizeof(l1fh->remote_sa); + rc = recvfrom(ofd->fd, msg->l1h, msgb_tailroom(msg), 0, + (struct sockaddr *) &l1fh->remote_sa, &l1fh->remote_sa_len); + if (rc < 0) { + perror("read from udp"); + msgb_free(msg); + return rc; + } else if (rc == 0) { + perror("len=0 read from udp"); + msgb_free(msg); + return rc; + } + msgb_put(msg, rc); + + struct gsm_pcu_if *pcu_prim = (gsm_pcu_if *)(msg->l1h); + rc = pcu_rx(pcu_prim->msg_type, pcu_prim); + return rc; +} + +/* callback when we can write to the UDP socket */ +static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg) +{ + int rc; + struct l1fwd_hdl *l1fh = (l1fwd_hdl *)ofd->data; + + //LOGP(DPCU, LOGL_ERROR, "UDP: Writing %u bytes for MQ_L1_WRITE queue\n", msgb_length(msg)); + + rc = sendto(ofd->fd, msgb_data(msg), msgb_length(msg), 0, + (const struct sockaddr *)&l1fh->remote_sa, l1fh->remote_sa_len); + if (rc < 0) { + LOGP(DPCU, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", + strerror(errno)); + return rc; + } else if (rc < (int)msgb_length(msg)) { + LOGP(DPCU, LOGL_ERROR, "short write to L1 msg_queue: " + "%u < %u\n", rc, msgb_length(msg)); + return -EIO; + } + + return 0; +} + +int pcu_l1if_open() +{ + struct femtol1_hdl *fl1h; + int rc; + + /* allocate new femtol1_handle */ + fl1h = talloc_zero(NULL, struct femtol1_hdl); + INIT_LLIST_HEAD(&fl1h->wlc_list); + + l1fh->fl1h = fl1h; + fl1h->priv = l1fh; + + struct osmo_wqueue * queue = &((l1fh->fl1h)->write_q); + osmo_wqueue_init(queue, 10); + queue->bfd.when |= BSC_FD_READ; + queue->bfd.data = l1fh; + queue->bfd.priv_nr = 0; + + /* Open UDP */ + struct osmo_wqueue *wq = &l1fh->udp_wq; + + osmo_wqueue_init(wq, 10); + wq->write_cb = udp_write_cb; + wq->read_cb = udp_read_cb; + wq->bfd.when |= BSC_FD_READ; + wq->bfd.data = l1fh; + wq->bfd.priv_nr = 0; + rc = osmo_sock_init_ofd(&wq->bfd, AF_UNSPEC, SOCK_DGRAM, + IPPROTO_UDP, NULL, PCU_L1_IF_PORT, + OSMO_SOCK_F_BIND); + if (rc < 0) { + perror("sock_init"); + exit(1); + } + + return 0; +} + +void pcu_l1if_close(void) +{ + gprs_bssgp_destroy(); + + /* FIXME: cleanup l1if */ + talloc_free(l1fh->fl1h); +} |