blob: 56cbd49d40fe8278ee32bea74f4886641948515b [file] [log] [blame]
Neels Hofmeyre2f24d52017-05-08 15:12:20 +02001/* Implementation for MSC decisions which interface to send messages out on. */
2
3/* (C) 2016 by sysmocom s.m.f.c GmbH <info@sysmocom.de>
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 Affero 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#include <osmocom/core/logging.h>
22
23#include <openbsc/debug.h>
24#include <openbsc/gsm_data.h>
25#include <openbsc/msc_ifaces.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020026#include <openbsc/iu.h>
27#include <openbsc/gsm_subscriber.h>
28#include <openbsc/transaction.h>
29#include <openbsc/mgcp.h>
30#include <openbsc/mgcpgw_client.h>
31#include <openbsc/vlr.h>
32
33#include "../../bscconfig.h"
34
35#ifdef BUILD_IU
36extern struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id,
37 uint32_t rtp_ip,
38 uint16_t rtp_port,
39 bool use_x213_nsap);
40#endif /* BUILD_IU */
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020041
42static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg)
43{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020044 DEBUGP(DMSC, "msc_tx %u bytes to %s via %s\n",
45 msg->len, vlr_subscr_name(conn->vsub),
46 ran_type_name(conn->via_ran));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020047 switch (conn->via_ran) {
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020048 case RAN_GERAN_A:
49 msg->dst = conn;
50 return a_tx(msg);
51
52 case RAN_UTRAN_IU:
53 msg->dst = conn->iu.ue_ctx;
54 return iu_tx(msg, 0);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020055
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020056 default:
57 LOGP(DMSC, LOGL_ERROR,
58 "msc_tx(): conn->via_ran invalid (%d)\n",
59 conn->via_ran);
60 return -1;
61 }
62}
63
64
65int msc_tx_dtap(struct gsm_subscriber_connection *conn,
66 struct msgb *msg)
67{
68 return msc_tx(conn, msg);
69}
70
71
72/* 9.2.5 CM service accept */
73int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
74{
75 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACC");
76 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
77
78 gh->proto_discr = GSM48_PDISC_MM;
79 gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
80
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020081 DEBUGP(DMM, "-> CM SERVICE ACCEPT %s\n",
82 vlr_subscr_name(conn->vsub));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020083
84 return msc_tx_dtap(conn, msg);
85}
86
87/* 9.2.6 CM service reject */
88int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
89 enum gsm48_reject_value value)
90{
91 struct msgb *msg;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020092 conn->received_cm_service_request = false;
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020093
94 msg = gsm48_create_mm_serv_rej(value);
95 if (!msg) {
96 LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
97 return -1;
98 }
99
100 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
101
102 return msc_tx_dtap(conn, msg);
103}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200104
105int msc_tx_common_id(struct gsm_subscriber_connection *conn)
106{
107 /* Common ID is only sent over IuCS */
108 if (conn->via_ran != RAN_UTRAN_IU) {
109 LOGP(DMM, LOGL_INFO,
110 "%s: Asked to transmit Common ID, but skipping"
111 " because this is not on UTRAN\n",
112 vlr_subscr_name(conn->vsub));
113 return 0;
114 }
115
116 DEBUGP(DIUCS, "%s: tx CommonID %s\n",
117 vlr_subscr_name(conn->vsub), conn->vsub->imsi);
118 return iu_tx_common_id(conn->iu.ue_ctx, conn->vsub->imsi);
119}
120
121#ifdef BUILD_IU
122static void iu_rab_act_cs(struct ue_conn_ctx *uectx, uint8_t rab_id,
123 uint32_t rtp_ip, uint16_t rtp_port)
124{
125 struct msgb *msg;
126 bool use_x213_nsap;
127 uint32_t conn_id = uectx->conn_id;
128
129 use_x213_nsap = (uectx->rab_assign_addr_enc == NSAP_ADDR_ENC_X213);
130
131 LOGP(DIUCS, LOGL_DEBUG, "Assigning RAB: conn_id=%u, rab_id=%d,"
132 " rtp=%x:%u, use_x213_nsap=%d\n", conn_id, rab_id, rtp_ip,
133 rtp_port, use_x213_nsap);
134
135 msg = ranap_new_msg_rab_assign_voice(rab_id, rtp_ip, rtp_port,
136 use_x213_nsap);
137 msg->l2h = msg->data;
138
139 if (iu_rab_act(uectx, msg))
140 LOGP(DIUCS, LOGL_ERROR, "Failed to send RAB Assignment:"
141 " conn_id=%d rab_id=%d rtp=%x:%u\n",
142 conn_id, rab_id, rtp_ip, rtp_port);
143}
144
145static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv)
146{
147 struct gsm_trans *trans = priv;
148 struct gsm_subscriber_connection *conn = trans->conn;
149 struct ue_conn_ctx *uectx = conn->iu.ue_ctx;
150 uint32_t rtp_ip;
151 int rc;
152
153 if (r->head.response_code != 200) {
154 LOGP(DMGCP, LOGL_ERROR,
155 "MGCPGW response yields error: %d %s\n",
156 r->head.response_code, r->head.comment);
157 goto rab_act_cs_error;
158 }
159
160 rc = mgcp_response_parse_params(r);
161 if (rc) {
162 LOGP(DMGCP, LOGL_ERROR,
163 "Cannot parse MGCP response, for %s\n",
164 vlr_subscr_name(trans->vsub));
165 goto rab_act_cs_error;
166 }
167
168 conn->iu.mgcp_rtp_port_cn = r->audio_port;
169
170 rtp_ip = mgcpgw_client_remote_addr_n(conn->network->mgcpgw.client);
171 iu_rab_act_cs(uectx, conn->iu.rab_id, rtp_ip,
172 conn->iu.mgcp_rtp_port_ue);
173 /* use_x213_nsap == 0 for ip.access nano3G */
174
175rab_act_cs_error:
176 /* FIXME abort call, invalidate conn, ... */
177 return;
178}
179
180static int conn_iu_rab_act_cs(struct gsm_trans *trans)
181{
182 struct gsm_subscriber_connection *conn = trans->conn;
183 struct mgcpgw_client *mgcp = conn->network->mgcpgw.client;
184 struct msgb *msg;
185
186 /* HACK. where to scope the RAB Id? At the conn / subscriber /
187 * ue_conn_ctx? */
188 static uint8_t next_rab_id = 1;
189 conn->iu.rab_id = next_rab_id ++;
190
191 conn->iu.mgcp_rtp_endpoint =
192 mgcpgw_client_next_endpoint(conn->network->mgcpgw.client);
193 /* HACK: the addresses should be known from CRCX response
194 * and config. */
195 conn->iu.mgcp_rtp_port_ue = 4000 + 2 * conn->iu.mgcp_rtp_endpoint;
196
197 /* Establish the RTP stream first as looping back to the originator.
198 * The MDCX will patch through to the counterpart. TODO: play a ring
199 * tone instead. */
200 msg = mgcp_msg_crcx(mgcp, conn->iu.mgcp_rtp_endpoint, trans->callref,
201 MGCP_CONN_LOOPBACK);
202 return mgcpgw_client_tx(mgcp, msg, mgcp_response_rab_act_cs_crcx, trans);
203}
204#endif
205
206int msc_call_assignment(struct gsm_trans *trans)
207{
208 struct gsm_subscriber_connection *conn = trans->conn;
209
210 switch (conn->via_ran) {
211 case RAN_GERAN_A:
212 LOGP(DMSC, LOGL_ERROR,
213 "msc_call_assignment(): A-interface BSSMAP Assignment"
214 " Request not yet implemented\n");
215 return -ENOTSUP;
216
217 case RAN_UTRAN_IU:
218#ifdef BUILD_IU
219 return conn_iu_rab_act_cs(trans);
220#else
221 LOGP(DMSC, LOGL_ERROR,
222 "msc_call_assignment(): cannot send RAB Activation, built without Iu support\n");
223 return -ENOTSUP;
224#endif
225
226 default:
227 LOGP(DMSC, LOGL_ERROR,
228 "msc_tx(): conn->via_ran invalid (%d)\n",
229 conn->via_ran);
230 return -EINVAL;
231 }
232}
233
234static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv);
235
236static void mgcp_bridge(struct gsm_trans *from, struct gsm_trans *to,
237 enum bridge_state state,
238 enum mgcp_connection_mode mode)
239{
240 struct gsm_subscriber_connection *conn1 = from->conn;
241 struct gsm_subscriber_connection *conn2 = to->conn;
242 struct mgcpgw_client *mgcp = conn1->network->mgcpgw.client;
243 const char *ip;
244 struct msgb *msg;
245
246 OSMO_ASSERT(mgcp);
247
248 from->bridge.peer = to;
249 from->bridge.state = state;
250
251 /* Loop back to the same MGCP GW */
252 ip = mgcpgw_client_remote_addr_str(mgcp);
253
254 msg = mgcp_msg_mdcx(mgcp,
255 conn1->iu.mgcp_rtp_endpoint,
256 ip, conn2->iu.mgcp_rtp_port_cn,
257 mode);
258 if (mgcpgw_client_tx(mgcp, msg, mgcp_response_bridge_mdcx, from))
259 LOGP(DMGCP, LOGL_ERROR,
260 "Failed to send MDCX message for %s\n",
261 vlr_subscr_name(from->vsub));
262}
263
264static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
265{
266 struct gsm_trans *trans = priv;
267 struct gsm_trans *peer = trans->bridge.peer;
268
269 switch (trans->bridge.state) {
270 case BRIDGE_STATE_LOOPBACK_PENDING:
271 trans->bridge.state = BRIDGE_STATE_LOOPBACK_ESTABLISHED;
272
273 switch (peer->bridge.state) {
274 case BRIDGE_STATE_LOOPBACK_PENDING:
275 /* Wait until the other is done as well. */
276 return;
277 case BRIDGE_STATE_LOOPBACK_ESTABLISHED:
278 /* Now that both are in loopback, switch both to
279 * forwarding. */
280 mgcp_bridge(trans, peer, BRIDGE_STATE_BRIDGE_PENDING,
281 MGCP_CONN_RECV_SEND);
282 mgcp_bridge(peer, trans, BRIDGE_STATE_BRIDGE_PENDING,
283 MGCP_CONN_RECV_SEND);
284 break;
285 default:
286 LOGP(DMGCP, LOGL_ERROR,
287 "Unexpected bridge state: %d for %s\n",
288 trans->bridge.state, vlr_subscr_name(trans->vsub));
289 break;
290 }
291 break;
292
293 case BRIDGE_STATE_BRIDGE_PENDING:
294 trans->bridge.state = BRIDGE_STATE_BRIDGE_ESTABLISHED;
295 break;
296
297 default:
298 LOGP(DMGCP, LOGL_ERROR,
299 "Unexpected bridge state: %d for %s\n",
300 trans->bridge.state, vlr_subscr_name(trans->vsub));
301 break;
302 }
303}
304
305int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2)
306{
307 /* First setup as loopback and configure the counterparts' endpoints,
308 * so that when transmission starts the originating addresses are
309 * already known to be valid. The mgcp callback will continue. */
310 mgcp_bridge(trans1, trans2, BRIDGE_STATE_LOOPBACK_PENDING,
311 MGCP_CONN_LOOPBACK);
312 mgcp_bridge(trans2, trans1, BRIDGE_STATE_LOOPBACK_PENDING,
313 MGCP_CONN_LOOPBACK);
314
315 return 0;
316}