blob: 535a7f00acfccb6d8436225483d854f1cac6382e [file] [log] [blame]
Andreas Eversberga23c7ee2012-12-18 10:47:28 +01001/* Interface handler for Sysmocom L1 (forwarding) */
2
3/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <stdint.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <errno.h>
26#include <fcntl.h>
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/socket.h>
31
32#include <netinet/in.h>
33#include <arpa/inet.h>
34
35#include <osmocom/core/talloc.h>
36#include <osmocom/core/utils.h>
37#include <osmocom/core/select.h>
38#include <osmocom/core/write_queue.h>
39#include <osmocom/core/msgb.h>
40#include <osmocom/core/socket.h>
41#include <osmocom/core/timer.h>
42#include <osmocom/gsm/gsm_utils.h>
43
44#include <sysmocom/femtobts/superfemto.h>
45#include <sysmocom/femtobts/gsml1prim.h>
46#include <sysmocom/femtobts/gsml1const.h>
47#include <sysmocom/femtobts/gsml1types.h>
48
49#include "gprs_debug.h"
50#include "sysmo_l1_if.h"
51
52
53#define L1FWD_L1_PORT 9999
54#define L1FWD_SYS_PORT 9998
55#define L1FWD_TCH_PORT 9997
56#define L1FWD_PDTCH_PORT 9996
57
58static const uint16_t fwd_udp_ports[] = {
59 [MQ_SYS_WRITE] = L1FWD_SYS_PORT,
60 [MQ_L1_WRITE] = L1FWD_L1_PORT,
61 [MQ_TCH_WRITE] = L1FWD_TCH_PORT,
62 [MQ_PDTCH_WRITE]= L1FWD_PDTCH_PORT,
63};
64
65static int fwd_read_cb(struct osmo_fd *ofd)
66{
67 struct msgb *msg = msgb_alloc_headroom(sizeof(SuperFemto_Prim_t) + 128,
68 128, "udp_rx");
69 struct femtol1_hdl *fl1h = ofd->data;
70 int rc;
71
72 if (!msg)
73 return -ENOMEM;
74
75 msg->l1h = msg->data;
76 rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg));
77 if (rc < 0) {
78 LOGP(DL1IF, LOGL_ERROR, "Short read from UDP\n");
79 msgb_free(msg);
80 return rc;
81 } else if (rc == 0) {
82 LOGP(DL1IF, LOGL_ERROR, "Len=0 from UDP\n");
83 msgb_free(msg);
84 return rc;
85 }
86 msgb_put(msg, rc);
87
88 if (ofd->priv_nr == MQ_SYS_WRITE)
89 rc = l1if_handle_sysprim(fl1h, msg);
90 else
91 rc = l1if_handle_l1prim(ofd->priv_nr, fl1h, msg);
92
93 return rc;
94}
95
96static int prim_write_cb(struct osmo_fd *ofd, struct msgb *msg)
97{
98 /* write to the fd */
99 return write(ofd->fd, msg->head, msg->len);
100}
101
102int l1if_transport_open(int q, struct femtol1_hdl *fl1h)
103{
104 int rc;
105 char *bts_host = getenv("L1FWD_BTS_HOST");
106
107 printf("sizeof(GsmL1_Prim_t) = %zu\n", sizeof(GsmL1_Prim_t));
108 printf("sizeof(SuperFemto_Prim_t) = %zu\n", sizeof(SuperFemto_Prim_t));
109
110 if (!bts_host) {
111 fprintf(stderr, "You have to set the L1FWD_BTS_HOST environment variable\n");
112 exit(2);
113 }
114
115 struct osmo_wqueue *wq = &fl1h->write_q[q];
116 struct osmo_fd *ofd = &wq->bfd;
117
118 osmo_wqueue_init(wq, 10);
119 wq->write_cb = prim_write_cb;
120 wq->read_cb = fwd_read_cb;
121
122 ofd->data = fl1h;
123 ofd->priv_nr = q;
124 ofd->when |= BSC_FD_READ;
125
126 rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
127 bts_host, fwd_udp_ports[q],
128 OSMO_SOCK_F_CONNECT);
129 if (rc < 0)
130 return rc;
131
132 return 0;
133}
134
135int l1if_transport_close(int q, struct femtol1_hdl *fl1h)
136{
137 struct osmo_wqueue *wq = &fl1h->write_q[q];
138 struct osmo_fd *ofd = &wq->bfd;
139
140 osmo_wqueue_clear(wq);
141 osmo_fd_unregister(ofd);
142 close(ofd->fd);
143
144 return 0;
145}