aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/msc/msc_vgcs.h
blob: 2b2f45d3105a03e8c48b26ec925d5e2409ecc372 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/* Handle a call via VGCS/VBCS (Voice Group/Broadcast Call Service). */
/*
 * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All Rights Reserved
 *
 * SPDX-License-Identifier: AGPL-3.0+
 *
 * Author: Andreas Eversberg
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once

#include <osmocom/msc/transaction.h>

#define GSM44068_ALLOC_SIZE        2048
#define GSM44068_ALLOC_HEADROOM    256

static inline struct msgb *gsm44068_msgb_alloc_name(const char *name)
{
	return msgb_alloc_headroom(GSM44068_ALLOC_SIZE, GSM44068_ALLOC_HEADROOM, name);
}

/* VGCS/VBS "call control" connection to each BSS */
struct vgcs_bss {
	struct llist_head list;		/* List entry */
	struct llist_head cell_list;	/* List of cells */
	struct gsm_trans *trans;	/* Back pointer to transaction */
	struct osmo_fsm_inst *fi;	/* State machine of each BSS */
	struct ran_conn *conn;		/* RAN ("SCCP") connection */
	enum trans_type trans_type;	/* Transaction type */
	uint32_t callref;		/* Callref */
	int pc;				/* Point code for debug purpose */
};

/* VGCS/VBS "resource control" connection to each cell in BSS */
struct vgcs_bss_cell {
	struct llist_head list_bss;	/* List entry in vgcs_bss */
	struct llist_head list_mgw;	/* List entry in MGW endpoint */
	struct vgcs_bss *bss;		/* Back pointer to vgcs_bss */
	struct vgcs_mgw_ep *mgw;	/* Back pointer to vgcs_mgw_ep */
	struct osmo_fsm_inst *fi;	/* State machine of each cell */
	int cell_id;			/* Id of cell (BTS) to use */
	struct ran_conn *conn;		/* RAN ("SCCP") connection */
	enum trans_type trans_type;	/* Transaction type */
	uint32_t callref;		/* Callref */
	int call_id;			/* Id of call (used for MGW connections) */
	int pc;				/* Point code for debug purpose */
	bool assigned;			/* Flags if assignment is complete */
	struct rtp_stream *rtps;	/* MGW connection process */
};

/* VGCS/VBS MGW endpoint for each call */
struct vgcs_mgw_ep {
	struct llist_head cell_list;	/* List of cells with connections */
	struct llist_head list;		/* List entry */
	struct osmo_fsm_inst *fi;	/* State machine of each cell */
	struct osmo_mgcpc_ep *mgw_ep;	/* MGW endpoint */
};

/* Events for the GCC/BCC state machine.
 * There is no primitive definition like MNGCC-* oder MNBCC-* in the standard. */
enum vgcs_gcc_fsm_event {
	/* The network sets up a call. */
	VGCS_GCC_EV_NET_SETUP,
	/* The network requests termination. */
	VGCS_GCC_EV_NET_TERM,
	/* The user sets up a call. */
	VGCS_GCC_EV_USER_SETUP,
	/* The user requests termination. */
	VGCS_GCC_EV_USER_TERM,
	/* BSS completed call establishment (all BSCs) */
	VGCS_GCC_EV_BSS_ESTABLISHED,
	/* Assignment was completed. */
	VGCS_GCC_EV_BSS_ASSIGN_CPL,
	/* Assignment failed. */
	VGCS_GCC_EV_BSS_ASSIGN_FAIL,
	/* BSS released call establishment (all BSCs) */
	VGCS_GCC_EV_BSS_RELEASED,
	/* Inactivity timeout */
	VGCS_GCC_EV_TIMEOUT,
};

/* 3GPP TS 44.068 6.1.2.2 States of GCC/BCC */
enum vgcs_gcc_fsm_state {
	/* No call. Initial state when instance is created. */
	VGCS_GCC_ST_N0_NULL = 0,
	/* An MS wants to establish a call. */
	VGCS_GCC_ST_N1_CALL_INITIATED,
	/* Call established in at least one cell. */
	VGCS_GCC_ST_N2_CALL_ACTIVE,
	/* Channel activation is requested, CONNECT already sent to MS. */
	VGCS_GCC_ST_N3_CALL_EST_PROC,
	/* Call termination is requested, waiting for all cells to confirm. */
	VGCS_GCC_ST_N4_TERMINATION_REQ,
};

const char *vgcs_bcc_gcc_state_name(struct osmo_fsm_inst *fi);

/* Events for the VGCS/VBS "call control" state machine */
enum vgcs_bss_fsm_event {
	/* Start a VGCS/VBS call using VGCS/VBS SETUP message */
	VGCS_BSS_EV_SETUP,
	/* VGCS/VBS SETUP ACK is received */
	VGCS_BSS_EV_SETUP_ACK,
	/* VGCS/VBS SETUP REFUSE is received */
	VGCS_BSS_EV_SETUP_REFUSE,
	/* VGCS/VBS ASSIGNMENT complete or failed */
	VGCS_BSS_EV_ACTIVE_OR_FAIL,
	/* Talker request */
	VGCS_BSS_EV_UL_REQUEST,
	/* Talker established uplink */
	VGCS_BSS_EV_UL_REQUEST_CNF,
	/* Talker send app data */
	VGCS_BSS_EV_UL_APP_DATA,
	/* Talker send signaling data */
	VGCS_BSS_EV_BSS_DTAP,
	/* Talker becomes listener */
	VGCS_BSS_EV_UL_RELEASE,
	/* Release channel towards BSS */
	VGCS_BSS_EV_CLEAR,
	/* Channel closed from BSS */
	VGCS_BSS_EV_CLOSE,
	/* Release is complete */
	VGCS_BSS_EV_RELEASED,
};

/* States of the VGCS/VBS "call control" state machine */
enum vgcs_bss_fsm_state {
	/* No call. Initial state when instance is created. */
	VGCS_BSS_ST_NULL = 0,
	/* VGCS/VBS SETUP is sent towards BSC */
	VGCS_BSS_ST_SETUP,
	/* VGCS/VBS ASSIGNMENT REQUEST is sent towards BSC */
	VGCS_BSS_ST_ASSIGNMENT,
	/* VGCS/VBS is establised */
	VGCS_BSS_ST_ACTIVE,
	/* CLEAR COMMAND was sent */
	VGCS_BSS_ST_RELEASE,
};

/* Events for the VGCS/VBS "resource control" state machine */
enum vgcs_cell_fsm_event {
	/* RTP stream gone */
	VGCS_CELL_EV_RTP_STREAM_GONE,
	/* RTP stream remote addr available */
	VGCS_CELL_EV_RTP_STREAM_ADDR_AVAILABLE,
	/* RTP stream established */
	VGCS_CELL_EV_RTP_STREAM_ESTABLISHED,
	/* Start a VGCS/VBS channel using VGCS/VBS ASSIGNMENT message */
	VGCS_CELL_EV_ASSIGN,
	/* VGCS/VBS ASSIGNMENT RESULT is received */
	VGCS_CELL_EV_ASSIGN_RES,
	/* VGCS/VBS ASSIGNMENT FAILURE is received */
	VGCS_CELL_EV_ASSIGN_FAIL,
	/* Release channel towards BSS */
	VGCS_CELL_EV_CLEAR,
	/* Channel closed from BSS */
	VGCS_CELL_EV_CLOSE,
	/* Release is complete */
	VGCS_CELL_EV_RELEASED,
};

/* States of the VGCS/VBS "resource control" state machine */
enum vgcs_cell_fsm_state {
	/* No call. Initial state when instance is created. */
	VGCS_CELL_ST_NULL = 0,
	/* VGCS/VBS ASSIGNMENT REQUEST is sent towards BSC */
	VGCS_CELL_ST_ASSIGNMENT,
	/* Channel is establised */
	VGCS_CELL_ST_ACTIVE,
	/* CLEAR COMMAND was sent */
	VGCS_CELL_ST_RELEASE,
};

/* Events for the VGCS/VBS MGW endpoint state machine */
enum vgcs_mgw_ep_fsm_event {
	/* MGW endpoint gone */
	VGCS_MGW_EP_EV_FREE,
	/* Destroy MGW endpoint */
	VGCS_MGW_EP_EV_CLEAR,
};

/* States of the VGCS/VBS MGW endpoint state machine */
enum vgcs_mgw_ep_fsm_state {
	VGCS_MGW_EP_ST_NULL = 0,
	/* MGW endpoint allocated */
	VGCS_MGW_EP_ST_ACTIVE,
};

const char *gsm44068_group_id_string(uint32_t callref);

struct gcr;

int gsm44068_rcv_rr(struct msc_a *msc_a, struct msgb *msg);
int gsm44068_rcv_bcc_gcc(struct msc_a *msc_a, struct gsm_trans *trans, struct msgb *msg);
const char *vgcs_vty_initiate(struct gsm_network *gsmnet, struct gcr *gcr);
const char *vgcs_vty_terminate(struct gsm_network *gsmnet, struct gcr *gcr);
void gsm44068_bcc_gcc_trans_free(struct gsm_trans *trans);

void vgcs_vbs_setup_ack(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_vbs_setup_refuse(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_vbs_assign_result(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg);
void vgcs_vbs_assign_fail(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg);
void vgcs_vbs_queuing_ind(struct vgcs_bss_cell *cell);
void vgcs_uplink_request(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_uplink_request_cnf(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_app_data(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_bss_dtap(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_uplink_release_ind(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_vbs_assign_status(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg);
void vgcs_vbs_clear_req_channel(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg);
void vgcs_vbs_clear_cpl_channel(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg);
void vgcs_vbs_clear_req(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_vbs_clear_cpl(struct vgcs_bss *bss, const struct ran_msg *ran_msg);
void vgcs_vbs_caller_assign_cpl(struct gsm_trans *trans);
void vgcs_vbs_caller_assign_fail(struct gsm_trans *trans);