blob: 1e7b4cd5122c0d5c78cd221033d01fdf3dd729b8 [file] [log] [blame]
Harald Welteb4771a62012-11-11 10:58:51 +01001/* UDP-Feed of measurement reports */
2
3#include <unistd.h>
4
Holger Hans Peter Freytherd1540982015-08-01 23:46:56 +00005#include <sys/socket.h>
6
Harald Welteb4771a62012-11-11 10:58:51 +01007#include <osmocom/core/msgb.h>
8#include <osmocom/core/socket.h>
9#include <osmocom/core/write_queue.h>
10#include <osmocom/core/talloc.h>
Neels Hofmeyr93bafb62017-01-13 03:12:08 +010011#include <osmocom/core/utils.h>
Harald Welteb4771a62012-11-11 10:58:51 +010012
13#include <osmocom/vty/command.h>
14#include <osmocom/vty/vty.h>
15
16#include <openbsc/meas_rep.h>
17#include <openbsc/signal.h>
18#include <openbsc/gsm_subscriber.h>
19#include <openbsc/meas_feed.h>
20#include <openbsc/vty.h>
Harald Welte2483f1b2016-06-19 18:06:02 +020021#include <openbsc/vlr.h>
Harald Welteb4771a62012-11-11 10:58:51 +010022
23#include "meas_feed.h"
24
25struct meas_feed_state {
26 struct osmo_wqueue wqueue;
27 char scenario[31+1];
28 char *dst_host;
29 uint16_t dst_port;
30};
31
32
33static struct meas_feed_state g_mfs;
34
35static int process_meas_rep(struct gsm_meas_rep *mr)
36{
37 struct msgb *msg;
38 struct meas_feed_meas *mfm;
Harald Welte2483f1b2016-06-19 18:06:02 +020039 struct vlr_subscr *vsub;
Harald Welteb4771a62012-11-11 10:58:51 +010040
41 /* ignore measurements as long as we don't know who it is */
Harald Welte2483f1b2016-06-19 18:06:02 +020042 if (!mr->lchan || !mr->lchan->conn || !mr->lchan->conn->vsub)
Harald Welteb4771a62012-11-11 10:58:51 +010043 return 0;
44
Harald Welte2483f1b2016-06-19 18:06:02 +020045 vsub = mr->lchan->conn->vsub;
Harald Welteb4771a62012-11-11 10:58:51 +010046
47 msg = msgb_alloc(sizeof(struct meas_feed_meas), "Meas. Feed");
48 if (!msg)
49 return 0;
50
51 /* fill in the header */
52 mfm = (struct meas_feed_meas *) msgb_put(msg, sizeof(*mfm));
53 mfm->hdr.msg_type = MEAS_FEED_MEAS;
54 mfm->hdr.version = MEAS_FEED_VERSION;
55
56 /* fill in MEAS_FEED_MEAS specific header */
Harald Welte2483f1b2016-06-19 18:06:02 +020057 osmo_strlcpy(mfm->imsi, vsub->imsi, sizeof(mfm->imsi));
58 osmo_strlcpy(mfm->name, vsub->name, sizeof(mfm->name));
Neels Hofmeyr93bafb62017-01-13 03:12:08 +010059 osmo_strlcpy(mfm->scenario, g_mfs.scenario, sizeof(mfm->scenario));
Harald Welteb4771a62012-11-11 10:58:51 +010060
61 /* copy the entire measurement report */
62 memcpy(&mfm->mr, mr, sizeof(mfm->mr));
63
Alexander Chemeris08c508f2015-08-20 20:48:39 -040064 /* copy channel information */
65 /* we assume that the measurement report always belong to some timeslot */
66 mfm->lchan_type = (uint8_t)mr->lchan->type;
67 mfm->pchan_type = (uint8_t)mr->lchan->ts->pchan;
68 mfm->bts_nr = mr->lchan->ts->trx->bts->nr;
69 mfm->trx_nr = mr->lchan->ts->trx->nr;
70 mfm->ts_nr = mr->lchan->ts->nr;
71 mfm->ss_nr = mr->lchan->nr;
72
Harald Welteb4771a62012-11-11 10:58:51 +010073 /* and send it to the socket */
Holger Hans Peter Freytherfd603ed2015-03-28 18:09:31 +010074 if (osmo_wqueue_enqueue(&g_mfs.wqueue, msg) != 0)
75 msgb_free(msg);
Harald Welteb4771a62012-11-11 10:58:51 +010076
77 return 0;
78}
79
80static int meas_feed_sig_cb(unsigned int subsys, unsigned int signal,
81 void *handler_data, void *signal_data)
82{
83 struct lchan_signal_data *sdata = signal_data;
84
85 if (subsys != SS_LCHAN)
86 return 0;
87
88 if (signal == S_LCHAN_MEAS_REP)
89 process_meas_rep(sdata->mr);
90
91 return 0;
92}
93
94static int feed_write_cb(struct osmo_fd *ofd, struct msgb *msg)
95{
96 return write(ofd->fd, msgb_data(msg), msgb_length(msg));
97}
98
Harald Welte8db07882015-01-01 13:06:48 +010099static int feed_read_cb(struct osmo_fd *ofd)
Harald Welteb4771a62012-11-11 10:58:51 +0100100{
101 int rc;
102 char buf[256];
103
104 rc = read(ofd->fd, buf, sizeof(buf));
105 ofd->fd &= ~BSC_FD_READ;
106
107 return rc;
108}
109
110int meas_feed_cfg_set(const char *dst_host, uint16_t dst_port)
111{
112 int rc;
113 int already_initialized = 0;
114
115 if (g_mfs.wqueue.bfd.fd)
116 already_initialized = 1;
117
118
119 if (already_initialized &&
120 !strcmp(dst_host, g_mfs.dst_host) &&
121 dst_port == g_mfs.dst_port)
122 return 0;
123
124 if (!already_initialized) {
125 osmo_wqueue_init(&g_mfs.wqueue, 10);
126 g_mfs.wqueue.write_cb = feed_write_cb;
127 g_mfs.wqueue.read_cb = feed_read_cb;
128 osmo_signal_register_handler(SS_LCHAN, meas_feed_sig_cb, NULL);
129 }
130
131 if (already_initialized) {
132 osmo_wqueue_clear(&g_mfs.wqueue);
133 osmo_fd_unregister(&g_mfs.wqueue.bfd);
134 close(g_mfs.wqueue.bfd.fd);
135 /* don't set to zero, as that would mean 'not yet initialized' */
136 g_mfs.wqueue.bfd.fd = -1;
137 }
138 rc = osmo_sock_init_ofd(&g_mfs.wqueue.bfd, AF_UNSPEC, SOCK_DGRAM,
139 IPPROTO_UDP, dst_host, dst_port,
140 OSMO_SOCK_F_CONNECT);
141 if (rc < 0)
142 return rc;
143
144 g_mfs.wqueue.bfd.when &= ~BSC_FD_READ;
145
146 if (g_mfs.dst_host)
147 talloc_free(g_mfs.dst_host);
148 g_mfs.dst_host = talloc_strdup(NULL, dst_host);
149 g_mfs.dst_port = dst_port;
150
151 return 0;
152}
153
154void meas_feed_cfg_get(char **host, uint16_t *port)
155{
156 *port = g_mfs.dst_port;
157 *host = g_mfs.dst_host;
158}
159
160void meas_feed_scenario_set(const char *name)
161{
Neels Hofmeyr93bafb62017-01-13 03:12:08 +0100162 osmo_strlcpy(g_mfs.scenario, name, sizeof(g_mfs.scenario));
Harald Welteb4771a62012-11-11 10:58:51 +0100163}
164
165const char *meas_feed_scenario_get(void)
166{
167 return g_mfs.scenario;
168}