blob: cbff7006c3f60c5d5c139384868aacfc5000416e [file] [log] [blame]
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The protocol implementation */
3
4/*
5 * (C) 2009-2014 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2011 by On-Waves
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020024#include <osmocom/core/talloc.h>
Stefan Sperling1e174872018-10-25 18:36:10 +020025#include <osmocom/vty/misc.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020026#include <osmocom/mgcp/mgcp.h>
Neels Hofmeyr67793542017-09-08 04:25:16 +020027#include <osmocom/mgcp/mgcp_common.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020028#include <osmocom/mgcp/mgcp_internal.h>
29#include <osmocom/mgcp/vty.h>
30#include <osmocom/mgcp/mgcp_conn.h>
Philipp Maier37d11c82018-02-01 14:38:12 +010031#include <osmocom/mgcp/mgcp_endp.h>
Philipp Maierc66ab2c2020-06-02 20:55:34 +020032#include <osmocom/mgcp/mgcp_trunk.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020033
34#include <string.h>
Philipp Maierbca0ef62018-07-09 17:20:51 +020035#include <inttypes.h>
Stefan Sperling12086582018-06-26 15:26:28 +020036#include <limits.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020037
38#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
39#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
40#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
Philipp Maier9fc8a022019-02-20 12:26:52 +010041#define RTP_TS101318_RFC5993_CONV_STR "Convert GSM-HR from TS101318 to RFC5993 and vice versa\n"
42
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020043
44static struct mgcp_config *g_cfg = NULL;
45
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020046struct cmd_node mgcp_node = {
47 MGCP_NODE,
48 "%s(config-mgcp)# ",
49 1,
50};
51
52struct cmd_node trunk_node = {
53 TRUNK_NODE,
54 "%s(config-mgcp-trunk)# ",
55 1,
56};
57
58static int config_write_mgcp(struct vty *vty)
59{
Philipp Maierd19de2e2020-06-03 13:55:33 +020060 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
61 OSMO_ASSERT(trunk);
Harald Weltec39b1bf2020-03-08 11:29:39 +010062
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020063 vty_out(vty, "mgcp%s", VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +020064 vty_out(vty, " domain %s%s", g_cfg->domain, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020065 if (g_cfg->local_ip)
66 vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +020067 vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
68 vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
69 vty_out(vty, " rtp port-range %u %u%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +020070 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end,
71 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020072 if (g_cfg->net_ports.bind_addr)
Philipp Maierf53796c2020-06-02 20:38:28 +020073 vty_out(vty, " rtp bind-ip %s%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +020074 g_cfg->net_ports.bind_addr, VTY_NEWLINE);
Philipp Maier1cb1e382017-11-02 17:16:04 +010075 if (g_cfg->net_ports.bind_addr_probe)
Philipp Maierf53796c2020-06-02 20:38:28 +020076 vty_out(vty, " rtp ip-probing%s", VTY_NEWLINE);
Philipp Maier1cb1e382017-11-02 17:16:04 +010077 else
Philipp Maierf53796c2020-06-02 20:38:28 +020078 vty_out(vty, " no rtp ip-probing%s", VTY_NEWLINE);
79 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
Harald Weltec39b1bf2020-03-08 11:29:39 +010080 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
Philipp Maierf53796c2020-06-02 20:38:28 +020081 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
Harald Weltec39b1bf2020-03-08 11:29:39 +010082 else if (trunk->keepalive_interval)
Philipp Maierf53796c2020-06-02 20:38:28 +020083 vty_out(vty, " rtp keep-alive %d%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +010084 trunk->keepalive_interval, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020085 else
Philipp Maierf53796c2020-06-02 20:38:28 +020086 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020087
Harald Weltec39b1bf2020-03-08 11:29:39 +010088 if (trunk->omit_rtcp)
Philipp Maierf53796c2020-06-02 20:38:28 +020089 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020090 else
Philipp Maierf53796c2020-06-02 20:38:28 +020091 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
Harald Weltec39b1bf2020-03-08 11:29:39 +010092 if (trunk->force_constant_ssrc
93 || trunk->force_aligned_timing
94 || trunk->rfc5993_hr_convert) {
Philipp Maierf53796c2020-06-02 20:38:28 +020095 vty_out(vty, " %srtp-patch ssrc%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +010096 trunk->force_constant_ssrc ? "" : "no ",
Philipp Maier87bd9be2017-08-22 16:35:41 +020097 VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +020098 vty_out(vty, " %srtp-patch timestamp%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +010099 trunk->force_aligned_timing ? "" : "no ",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200100 VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200101 vty_out(vty, " %srtp-patch rfc5993hr%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +0100102 trunk->rfc5993_hr_convert ? "" : "no ",
Philipp Maier9fc8a022019-02-20 12:26:52 +0100103 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200104 } else
Philipp Maierf53796c2020-06-02 20:38:28 +0200105 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
Harald Weltec39b1bf2020-03-08 11:29:39 +0100106 if (trunk->audio_fmtp_extra)
Philipp Maierf53796c2020-06-02 20:38:28 +0200107 vty_out(vty, " sdp audio fmtp-extra %s%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +0100108 trunk->audio_fmtp_extra, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200109 vty_out(vty, " %ssdp audio-payload send-ptime%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +0100110 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200111 vty_out(vty, " %ssdp audio-payload send-name%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +0100112 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200113 vty_out(vty, " loop %u%s", ! !trunk->audio_loop, VTY_NEWLINE);
114 vty_out(vty, " number endpoints %u%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +0100115 trunk->vty_number_endpoints - 1, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200116 vty_out(vty, " %sallow-transcoding%s",
Harald Weltec39b1bf2020-03-08 11:29:39 +0100117 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200118 if (g_cfg->call_agent_addr)
Philipp Maierf53796c2020-06-02 20:38:28 +0200119 vty_out(vty, " call-agent ip %s%s", g_cfg->call_agent_addr,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200120 VTY_NEWLINE);
121 if (g_cfg->force_ptime > 0)
Philipp Maierf53796c2020-06-02 20:38:28 +0200122 vty_out(vty, " rtp force-ptime %d%s", g_cfg->force_ptime,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200123 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200124
125 switch (g_cfg->osmux) {
126 case OSMUX_USAGE_ON:
Philipp Maierf53796c2020-06-02 20:38:28 +0200127 vty_out(vty, " osmux on%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200128 break;
129 case OSMUX_USAGE_ONLY:
Philipp Maierf53796c2020-06-02 20:38:28 +0200130 vty_out(vty, " osmux only%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200131 break;
132 case OSMUX_USAGE_OFF:
133 default:
Philipp Maierf53796c2020-06-02 20:38:28 +0200134 vty_out(vty, " osmux off%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200135 break;
136 }
137 if (g_cfg->osmux) {
Philipp Maierf53796c2020-06-02 20:38:28 +0200138 vty_out(vty, " osmux bind-ip %s%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200139 g_cfg->osmux_addr, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200140 vty_out(vty, " osmux batch-factor %d%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200141 g_cfg->osmux_batch, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200142 vty_out(vty, " osmux batch-size %u%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200143 g_cfg->osmux_batch_size, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200144 vty_out(vty, " osmux port %u%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200145 g_cfg->osmux_port, VTY_NEWLINE);
Philipp Maierf53796c2020-06-02 20:38:28 +0200146 vty_out(vty, " osmux dummy %s%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200147 g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
148 }
Oliver Smithe36b7752019-01-22 16:31:36 +0100149
150 if (g_cfg->conn_timeout)
Philipp Maierf53796c2020-06-02 20:38:28 +0200151 vty_out(vty, " conn-timeout %u%s", g_cfg->conn_timeout, VTY_NEWLINE);
Oliver Smithe36b7752019-01-22 16:31:36 +0100152
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200153 return CMD_SUCCESS;
154}
155
Philipp Maiercede2a42018-07-03 14:14:21 +0200156static void dump_rtp_end(struct vty *vty, struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200157{
Philipp Maiercede2a42018-07-03 14:14:21 +0200158 struct mgcp_rtp_state *state = &conn->state;
159 struct mgcp_rtp_end *end = &conn->end;
Philipp Maierbc0346e2018-06-07 09:52:16 +0200160 struct mgcp_rtp_codec *codec = end->codec;
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100161 struct rate_ctr *tx_packets, *tx_bytes;
162 struct rate_ctr *rx_packets, *rx_bytes;
Philipp Maiercede2a42018-07-03 14:14:21 +0200163 struct rate_ctr *dropped_packets;
164
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100165 tx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR];
166 tx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR];
167 rx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
168 rx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR];
Philipp Maiercede2a42018-07-03 14:14:21 +0200169 dropped_packets = &conn->rate_ctr_group->ctr[RTP_DROPPED_PACKETS_CTR];
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200170
171 vty_out(vty,
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100172 " Packets Sent: %" PRIu64 " (%" PRIu64 " bytes total)%s"
173 " Packets Received: %" PRIu64 " (%" PRIu64 " bytes total)%s"
Philipp Maierbca0ef62018-07-09 17:20:51 +0200174 " Timestamp Errs: %" PRIu64 "->%" PRIu64 "%s"
175 " Dropped Packets: %" PRIu64 "%s"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200176 " Payload Type: %d Rate: %u Channels: %d %s"
177 " Frame Duration: %u Frame Denominator: %u%s"
178 " FPP: %d Packet Duration: %u%s"
179 " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
180 " Output-Enabled: %d Force-PTIME: %d%s",
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100181 tx_packets->current, tx_bytes->current, VTY_NEWLINE,
182 rx_packets->current, rx_bytes->current, VTY_NEWLINE,
Philipp Maier9e1d1642018-05-09 16:26:34 +0200183 state->in_stream.err_ts_ctr->current,
184 state->out_stream.err_ts_ctr->current,
185 VTY_NEWLINE,
Philipp Maiercede2a42018-07-03 14:14:21 +0200186 dropped_packets->current, VTY_NEWLINE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200187 codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200188 codec->frame_duration_num, codec->frame_duration_den,
189 VTY_NEWLINE, end->frames_per_packet, end->packet_duration_ms,
190 VTY_NEWLINE, end->fmtp_extra, codec->audio_name,
191 codec->subtype_name, VTY_NEWLINE, end->output_enabled,
192 end->force_output_ptime, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200193}
194
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200195static void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp,
Stefan Sperling12086582018-06-26 15:26:28 +0200196 int trunk_nr, enum mgcp_trunk_type trunk_type, int show_stats)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200197{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200198 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200199
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200200 vty_out(vty, "%s trunk %d endpoint %s:%s",
201 trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr, endp->name, VTY_NEWLINE);
Philipp Maier8d6a1932020-06-18 12:19:31 +0200202 vty_out(vty, " Availability: %s%s",
203 mgcp_endp_avail(endp) ? "available" : "not in service", VTY_NEWLINE);
Stefan Sperling12086582018-06-26 15:26:28 +0200204
205 if (llist_empty(&endp->conns)) {
206 vty_out(vty, " No active connections%s", VTY_NEWLINE);
207 return;
208 }
209
210 llist_for_each_entry(conn, &endp->conns, entry) {
211 vty_out(vty, " CONN: %s%s", mgcp_conn_dump(conn), VTY_NEWLINE);
212
213 if (show_stats) {
Oliver Smithe36b7752019-01-22 16:31:36 +0100214 if (endp->cfg->conn_timeout) {
215 struct timeval remaining;
216 osmo_timer_remaining(&conn->watchdog, NULL, &remaining);
217 vty_out(vty, " Currently remaining timeout (seconds): %d.%06d%s",
218 (int)remaining.tv_sec, (int)remaining.tv_usec, VTY_NEWLINE);
219 }
220
Stefan Sperling12086582018-06-26 15:26:28 +0200221 /* FIXME: Also add verbosity for other
222 * connection types (E1) as soon as
223 * the implementation is available */
224 if (conn->type == MGCP_CONN_TYPE_RTP) {
225 dump_rtp_end(vty, &conn->u.rtp);
226 }
227 }
228 }
229}
230
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200231static void dump_ratectr_global(struct vty *vty, struct mgcp_ratectr_global *ratectr)
232{
233 vty_out(vty, "%s", VTY_NEWLINE);
234 vty_out(vty, "Rate counters (global):%s", VTY_NEWLINE);
235
236 if (ratectr->mgcp_general_ctr_group) {
237 vty_out(vty, " %s:%s",
238 ratectr->mgcp_general_ctr_group->desc->
239 group_description, VTY_NEWLINE);
240 vty_out_rate_ctr_group_fmt(vty,
241 " %25n: %10c (%S/s %M/m %H/h %D/d) %d",
242 ratectr->mgcp_general_ctr_group);
243 }
244}
245
246static void dump_ratectr_trunk(struct vty *vty, struct mgcp_ratectr_trunk *ratectr)
247{
248 vty_out(vty, "%s", VTY_NEWLINE);
249 vty_out(vty, "Rate counters (trunk):%s", VTY_NEWLINE);
250
251 if (ratectr->mgcp_crcx_ctr_group) {
252 vty_out(vty, " %s:%s",
253 ratectr->mgcp_crcx_ctr_group->desc->group_description,
254 VTY_NEWLINE);
255 vty_out_rate_ctr_group_fmt(vty,
256 " %25n: %10c (%S/s %M/m %H/h %D/d) %d",
257 ratectr->mgcp_crcx_ctr_group);
258 }
259 if (ratectr->mgcp_dlcx_ctr_group) {
260 vty_out(vty, " %s:%s",
261 ratectr->mgcp_dlcx_ctr_group->desc->group_description,
262 VTY_NEWLINE);
263 vty_out_rate_ctr_group_fmt(vty,
264 " %25n: %10c (%S/s %M/m %H/h %D/d) %d",
265 ratectr->mgcp_dlcx_ctr_group);
266 }
267 if (ratectr->mgcp_mdcx_ctr_group) {
268 vty_out(vty, " %s:%s",
269 ratectr->mgcp_mdcx_ctr_group->desc->group_description,
270 VTY_NEWLINE);
271 vty_out_rate_ctr_group_fmt(vty,
272 " %25n: %10c (%S/s %M/m %H/h %D/d) %d",
273 ratectr->mgcp_mdcx_ctr_group);
274 }
275 if (ratectr->all_rtp_conn_stats) {
276 vty_out(vty, " %s:%s",
277 ratectr->all_rtp_conn_stats->desc->group_description,
278 VTY_NEWLINE);
279 vty_out_rate_ctr_group_fmt(vty,
280 " %25n: %10c (%S/s %M/m %H/h %D/d) %d",
281 ratectr->all_rtp_conn_stats);
282 }
283}
284
285
286static void dump_trunk(struct vty *vty, struct mgcp_trunk *trunk, int show_stats)
Stefan Sperling12086582018-06-26 15:26:28 +0200287{
288 int i;
289
290 vty_out(vty, "%s trunk %d with %d endpoints:%s",
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200291 trunk->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
292 trunk->trunk_nr, trunk->number_endpoints - 1, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200293
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200294 if (!trunk->endpoints) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200295 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
296 return;
297 }
298
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200299 for (i = 0; i < trunk->number_endpoints; ++i) {
300 struct mgcp_endpoint *endp = trunk->endpoints[i];
301 dump_endpoint(vty, endp, trunk->trunk_nr, trunk->trunk_type,
302 show_stats);
303 if (i < trunk->number_endpoints - 1)
Stefan Sperling12086582018-06-26 15:26:28 +0200304 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200305 }
Stefan Sperling1e174872018-10-25 18:36:10 +0200306
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200307 if (show_stats)
308 dump_ratectr_trunk(vty, &trunk->ratectr);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200309}
310
Stefan Sperling12086582018-06-26 15:26:28 +0200311#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
312
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200313DEFUN(show_mcgp, show_mgcp_cmd,
314 "show mgcp [stats]",
315 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200316 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200317 "Include Statistics\n")
318{
Philipp Maier14b27a82020-06-02 20:15:30 +0200319 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200320 int show_stats = argc >= 1;
321
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200322 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200323 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200324
325 if (g_cfg->osmux)
Pau Espin Pedrol8de58e72019-04-24 13:33:46 +0200326 vty_out(vty, "Osmux used CID: %d%s", osmux_cid_pool_count_used(),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200327 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200328
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200329 if (show_stats)
330 dump_ratectr_global(vty, &g_cfg->ratectr);
331
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200332 return CMD_SUCCESS;
333}
334
Stefan Sperling12086582018-06-26 15:26:28 +0200335static void
Philipp Maier14b27a82020-06-02 20:15:30 +0200336dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk *trunk, const char *epname)
Stefan Sperling12086582018-06-26 15:26:28 +0200337{
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200338 struct mgcp_endpoint *endp;
Stefan Sperling12086582018-06-26 15:26:28 +0200339
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200340 if (trunk) {
341 /* If a trunk is given, search on that specific trunk only */
342 endp = mgcp_endp_by_name_trunk(NULL, epname, trunk);
343 if (!endp) {
344 vty_out(vty, "endpoint %s not configured on trunk %d%s", epname, trunk->trunk_nr, VTY_NEWLINE);
345 return;
346 }
347 } else {
348 /* If no trunk is given, search on all possible trunks */
349 endp = mgcp_endp_by_name(NULL, epname, g_cfg);
350 if (!endp) {
351 vty_out(vty, "endpoint %s not configured%s", epname, VTY_NEWLINE);
352 return;
Stefan Sperling12086582018-06-26 15:26:28 +0200353 }
354 }
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200355
356 trunk = endp->trunk;
357 dump_endpoint(vty, endp, trunk->trunk_nr, trunk->trunk_type, true);
Stefan Sperling12086582018-06-26 15:26:28 +0200358}
359
360DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
361 "show mgcp endpoint NAME",
362 SHOW_STR
363 SHOW_MGCP_STR
364 "Display information about an endpoint\n" "The name of the endpoint\n")
365{
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200366 dump_mgcp_endpoint(vty, NULL, argv[0]);
Stefan Sperling12086582018-06-26 15:26:28 +0200367 return CMD_SUCCESS;
368}
369
370DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
371 "show mgcp trunk <0-64> endpoint NAME",
372 SHOW_STR
373 SHOW_MGCP_STR
374 "Display information about a trunk\n" "Trunk number\n"
375 "Display information about an endpoint\n" "The name of the endpoint\n")
376{
Philipp Maier14b27a82020-06-02 20:15:30 +0200377 struct mgcp_trunk *trunk;
Stefan Sperling12086582018-06-26 15:26:28 +0200378 int trunkidx = atoi(argv[0]);
379
Philipp Maierd19de2e2020-06-03 13:55:33 +0200380 trunk = mgcp_trunk_by_num(g_cfg, trunkidx);
Stefan Sperling12086582018-06-26 15:26:28 +0200381 if (!trunk) {
382 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
383 return CMD_WARNING;
384 }
385
386 dump_mgcp_endpoint(vty, trunk, argv[1]);
387 return CMD_SUCCESS;
388}
389
Philipp Maier87bd9be2017-08-22 16:35:41 +0200390DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200391{
392 vty->node = MGCP_NODE;
393 return CMD_SUCCESS;
394}
395
396DEFUN(cfg_mgcp_local_ip,
397 cfg_mgcp_local_ip_cmd,
398 "local ip A.B.C.D",
399 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200400 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200401{
402 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
403 return CMD_SUCCESS;
404}
405
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200406#define BIND_STR "Listen/Bind related socket option\n"
407DEFUN(cfg_mgcp_bind_ip,
408 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200409 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200410{
411 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
412 return CMD_SUCCESS;
413}
414
415DEFUN(cfg_mgcp_bind_port,
416 cfg_mgcp_bind_port_cmd,
417 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200418 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200419{
420 unsigned int port = atoi(argv[0]);
421 g_cfg->source_port = port;
422 return CMD_SUCCESS;
423}
424
425DEFUN(cfg_mgcp_bind_early,
426 cfg_mgcp_bind_early_cmd,
427 "bind early (0|1)",
428 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200429 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200430{
431 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
432 return CMD_WARNING;
433}
434
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200435#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200436#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200437#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200438#define RANGE_START_STR "Start of the range of ports\n"
439#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200440
Philipp Maierf1889d82017-11-08 14:59:39 +0100441DEFUN(cfg_mgcp_rtp_port_range,
442 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200443 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200444 RTP_STR "Range of ports to use for the NET side\n"
445 RANGE_START_STR RANGE_END_STR)
446{
Philipp Maiera19547b2018-05-22 13:44:34 +0200447 int start;
448 int end;
449
450 start = atoi(argv[0]);
451 end = atoi(argv[1]);
452
453 if (end < start) {
454 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
455 end, start, VTY_NEWLINE);
456 return CMD_WARNING;
457 }
458
459 if (start & 1) {
460 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
461 start, start & 0xFFFE, VTY_NEWLINE);
462 start &= 0xFFFE;
463 }
464
465 if ((end & 1) == 0) {
466 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
467 end, end | 1, VTY_NEWLINE);
468 end |= 1;
469 }
470
471 g_cfg->net_ports.range_start = start;
472 g_cfg->net_ports.range_end = end;
473 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
474
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200475 return CMD_SUCCESS;
476}
Philipp Maierf1889d82017-11-08 14:59:39 +0100477ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
478 cfg_mgcp_rtp_net_range_cmd,
479 "rtp net-range <0-65534> <0-65534>",
480 RTP_STR "Range of ports to use for the NET side\n"
481 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200482
Philipp Maierf1889d82017-11-08 14:59:39 +0100483DEFUN(cfg_mgcp_rtp_bind_ip,
484 cfg_mgcp_rtp_bind_ip_cmd,
485 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200486 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
487{
488 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
489 return CMD_SUCCESS;
490}
Philipp Maierf1889d82017-11-08 14:59:39 +0100491ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
492 cfg_mgcp_rtp_net_bind_ip_cmd,
493 "rtp net-bind-ip A.B.C.D",
494 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200495
Philipp Maierf1889d82017-11-08 14:59:39 +0100496DEFUN(cfg_mgcp_rtp_no_bind_ip,
497 cfg_mgcp_rtp_no_bind_ip_cmd,
498 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200499 NO_STR RTP_STR "Bind endpoints facing the Network\n"
500 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200501{
502 talloc_free(g_cfg->net_ports.bind_addr);
503 g_cfg->net_ports.bind_addr = NULL;
504 return CMD_SUCCESS;
505}
Philipp Maierf1889d82017-11-08 14:59:39 +0100506ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
507 cfg_mgcp_rtp_no_net_bind_ip_cmd,
508 "no rtp net-bind-ip",
509 NO_STR RTP_STR "Bind endpoints facing the Network\n"
510 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200511
Philipp Maier1cb1e382017-11-02 17:16:04 +0100512DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
513 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
514 "rtp ip-probing",
515 RTP_STR "automatic rtp bind ip selection\n")
516{
517 g_cfg->net_ports.bind_addr_probe = true;
518 return CMD_SUCCESS;
519}
520
521DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
522 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
523 "no rtp ip-probing",
524 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
525{
526 g_cfg->net_ports.bind_addr_probe = false;
527 return CMD_SUCCESS;
528}
529
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200530DEFUN(cfg_mgcp_rtp_ip_dscp,
531 cfg_mgcp_rtp_ip_dscp_cmd,
532 "rtp ip-dscp <0-255>",
533 RTP_STR
534 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
535{
536 int dscp = atoi(argv[0]);
537 g_cfg->endp_dscp = dscp;
538 return CMD_SUCCESS;
539}
540
541ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200542 "rtp ip-tos <0-255>",
543 RTP_STR
544 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
545#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
Philipp Maier21be42a2020-05-29 21:39:48 +0200546DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200547 cfg_mgcp_rtp_force_ptime_cmd,
548 "rtp force-ptime (10|20|40)",
549 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200550 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200551{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200552 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200553 return CMD_SUCCESS;
554}
555
556DEFUN(cfg_mgcp_no_rtp_force_ptime,
557 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200558 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200559{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200560 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200561 return CMD_SUCCESS;
562}
563
564DEFUN(cfg_mgcp_sdp_fmtp_extra,
565 cfg_mgcp_sdp_fmtp_extra_cmd,
566 "sdp audio fmtp-extra .NAME",
567 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
568 "Extra Information\n")
569{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200570 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
571 OSMO_ASSERT(trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200572 char *txt = argv_concat(argv, argc, 0);
573 if (!txt)
574 return CMD_WARNING;
575
Philipp Maierd19de2e2020-06-03 13:55:33 +0200576 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200577 talloc_free(txt);
578 return CMD_SUCCESS;
579}
580
581DEFUN(cfg_mgcp_allow_transcoding,
582 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200583 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200584{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200585 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
586 OSMO_ASSERT(trunk);
587 trunk->no_audio_transcoding = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200588 return CMD_SUCCESS;
589}
590
591DEFUN(cfg_mgcp_no_allow_transcoding,
592 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200593 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200594{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200595 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
596 OSMO_ASSERT(trunk);
597 trunk->no_audio_transcoding = 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200598 return CMD_SUCCESS;
599}
600
601#define SDP_STR "SDP File related options\n"
602#define AUDIO_STR "Audio payload options\n"
Philipp Maier7f90ddb2020-06-02 21:52:53 +0200603DEFUN_DEPRECATED(cfg_mgcp_sdp_payload_number,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200604 cfg_mgcp_sdp_payload_number_cmd,
605 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200606 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200607{
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200608 return CMD_SUCCESS;
609}
610
Philipp Maier87bd9be2017-08-22 16:35:41 +0200611ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
612 cfg_mgcp_sdp_payload_number_cmd_old,
613 "sdp audio payload number <0-255>",
614 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200615
Philipp Maier7f90ddb2020-06-02 21:52:53 +0200616DEFUN_DEPRECATED(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200617 cfg_mgcp_sdp_payload_name_cmd,
618 "sdp audio-payload name NAME",
619 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
620{
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200621 return CMD_SUCCESS;
622}
623
624ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200625 "sdp audio payload name NAME",
626 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200627
Philipp Maier21be42a2020-05-29 21:39:48 +0200628DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200629 cfg_mgcp_sdp_payload_send_ptime_cmd,
630 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200631 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200632{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200633 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
634 OSMO_ASSERT(trunk);
635 trunk->audio_send_ptime = 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200636 return CMD_SUCCESS;
637}
638
639DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
640 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
641 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200642 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200643{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200644 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
645 OSMO_ASSERT(trunk);
646 trunk->audio_send_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200647 return CMD_SUCCESS;
648}
649
650DEFUN(cfg_mgcp_sdp_payload_send_name,
651 cfg_mgcp_sdp_payload_send_name_cmd,
652 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200653 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200654{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200655 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
656 OSMO_ASSERT(trunk);
657 trunk->audio_send_name = 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200658 return CMD_SUCCESS;
659}
660
661DEFUN(cfg_mgcp_no_sdp_payload_send_name,
662 cfg_mgcp_no_sdp_payload_send_name_cmd,
663 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200664 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200665{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200666 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
667 OSMO_ASSERT(trunk);
668 trunk->audio_send_name = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200669 return CMD_SUCCESS;
670}
671
672DEFUN(cfg_mgcp_loop,
673 cfg_mgcp_loop_cmd,
674 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200675 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200676{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200677 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
678 OSMO_ASSERT(trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200679 if (g_cfg->osmux) {
680 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
681 return CMD_WARNING;
682 }
Philipp Maierd19de2e2020-06-03 13:55:33 +0200683 trunk->audio_loop = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200684 return CMD_SUCCESS;
685}
686
687DEFUN(cfg_mgcp_force_realloc,
688 cfg_mgcp_force_realloc_cmd,
689 "force-realloc (0|1)",
690 "Force endpoint reallocation when the endpoint is still seized\n"
691 "Don't force reallocation\n" "force reallocation\n")
692{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200693 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
694 OSMO_ASSERT(trunk);
695 trunk->force_realloc = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200696 return CMD_SUCCESS;
697}
698
Philipp Maier87bd9be2017-08-22 16:35:41 +0200699DEFUN(cfg_mgcp_rtp_accept_all,
700 cfg_mgcp_rtp_accept_all_cmd,
701 "rtp-accept-all (0|1)",
702 "Accept all RTP packets, even when the originating IP/Port does not match\n"
703 "enable filter\n" "disable filter\n")
704{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200705 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
706 OSMO_ASSERT(trunk);
707 trunk->rtp_accept_all = atoi(argv[0]);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200708 return CMD_SUCCESS;
709}
710
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200711DEFUN(cfg_mgcp_number_endp,
712 cfg_mgcp_number_endp_cmd,
713 "number endpoints <0-65534>",
714 "Number options\n" "Endpoints available\n" "Number endpoints\n")
715{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200716 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
717 OSMO_ASSERT(trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200718 /* + 1 as we start counting at one */
Philipp Maierd19de2e2020-06-03 13:55:33 +0200719 trunk->vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200720 return CMD_SUCCESS;
721}
722
Philipp Maier87bd9be2017-08-22 16:35:41 +0200723DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200724{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200725 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, 0);
726 trunk->omit_rtcp = 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200727 return CMD_SUCCESS;
728}
729
730DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200731 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200732{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200733 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
734 OSMO_ASSERT(trunk);
735 trunk->omit_rtcp = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200736 return CMD_SUCCESS;
737}
738
739DEFUN(cfg_mgcp_patch_rtp_ssrc,
740 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200741 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200742{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200743 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
744 OSMO_ASSERT(trunk);
745 trunk->force_constant_ssrc = 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200746 return CMD_SUCCESS;
747}
748
749DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
750 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200751 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200752{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200753 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
754 OSMO_ASSERT(trunk);
755 trunk->force_constant_ssrc = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200756 return CMD_SUCCESS;
757}
758
759DEFUN(cfg_mgcp_patch_rtp_ts,
760 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200761 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200762{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200763 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
764 OSMO_ASSERT(trunk);
765 trunk->force_aligned_timing = 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200766 return CMD_SUCCESS;
767}
768
769DEFUN(cfg_mgcp_no_patch_rtp_ts,
770 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200771 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200772{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200773 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
774 OSMO_ASSERT(trunk);
775 trunk->force_aligned_timing = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200776 return CMD_SUCCESS;
777}
778
Philipp Maier9fc8a022019-02-20 12:26:52 +0100779DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
780 cfg_mgcp_patch_rtp_rfc5993hr_cmd,
781 "rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
782{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200783 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
784 OSMO_ASSERT(trunk);
785 trunk->rfc5993_hr_convert = true;
Philipp Maier9fc8a022019-02-20 12:26:52 +0100786 return CMD_SUCCESS;
787}
788
789DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
790 cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
791 "no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
792{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200793 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
794 OSMO_ASSERT(trunk);
795 trunk->rfc5993_hr_convert = false;
Philipp Maier9fc8a022019-02-20 12:26:52 +0100796 return CMD_SUCCESS;
797}
798
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200799DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200800 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200801{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200802 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
803 OSMO_ASSERT(trunk);
804 trunk->force_constant_ssrc = 0;
805 trunk->force_aligned_timing = 0;
806 trunk->rfc5993_hr_convert = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200807 return CMD_SUCCESS;
808}
809
810DEFUN(cfg_mgcp_rtp_keepalive,
811 cfg_mgcp_rtp_keepalive_cmd,
812 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200813 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200814{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200815 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
816 OSMO_ASSERT(trunk);
817 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200818 return CMD_SUCCESS;
819}
820
821DEFUN(cfg_mgcp_rtp_keepalive_once,
822 cfg_mgcp_rtp_keepalive_once_cmd,
823 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200824 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200825{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200826 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
827 OSMO_ASSERT(trunk);
828 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200829 return CMD_SUCCESS;
830}
831
832DEFUN(cfg_mgcp_no_rtp_keepalive,
833 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200834 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200835{
Philipp Maierd19de2e2020-06-03 13:55:33 +0200836 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
837 OSMO_ASSERT(trunk);
838 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200839 return CMD_SUCCESS;
840}
841
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200842#define CALL_AGENT_STR "Callagent information\n"
843DEFUN(cfg_mgcp_agent_addr,
844 cfg_mgcp_agent_addr_cmd,
845 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200846 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200847{
848 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
849 return CMD_SUCCESS;
850}
851
852ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200853 "call agent ip A.B.C.D",
854 CALL_AGENT_STR CALL_AGENT_STR IP_STR
855 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200856
Philipp Maier21be42a2020-05-29 21:39:48 +0200857DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200858 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200859{
Philipp Maier14b27a82020-06-02 20:15:30 +0200860 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200861 int index = atoi(argv[0]);
862
Philipp Maierd19de2e2020-06-03 13:55:33 +0200863 /* Due to historical reasons, the trunk id number 0 is reserved for the
864 * virtual trunk. This trunk is configured with separate VTY
865 * parameters, so we restrict the access to trunks with id numbers
866 * greater than 0. */
867
Philipp Maierc66ab2c2020-06-02 20:55:34 +0200868 trunk = mgcp_trunk_by_num(g_cfg, index);
Harald Weltec39b1bf2020-03-08 11:29:39 +0100869 if (!trunk) {
870 trunk = mgcp_trunk_alloc(g_cfg, MGCP_TRUNK_E1, index);
Philipp Maier2d681fd2020-05-29 16:20:25 +0200871 if (!trunk) {
872 vty_out(vty, "%%Unable to allocate trunk %u.%s",
873 index, VTY_NEWLINE);
Harald Weltec39b1bf2020-03-08 11:29:39 +0100874 return CMD_WARNING;
Philipp Maier2d681fd2020-05-29 16:20:25 +0200875 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200876 }
877
878 vty->node = TRUNK_NODE;
879 vty->index = trunk;
880 return CMD_SUCCESS;
881}
882
883static int config_write_trunk(struct vty *vty)
884{
Philipp Maier14b27a82020-06-02 20:15:30 +0200885 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200886
887 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maierd19de2e2020-06-03 13:55:33 +0200888
889 /* Due to historical reasons, the virtual trunk is configured
890 using separate VTY parameters, so we omit writing the trunk
891 config of trunk 0 here. The configuration for the virtual
892 trunk is written by config_write_mgcp(). */
893
894 if (trunk->trunk_nr == MGCP_VIRT_TRUNK_ID)
895 continue;
896
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200897 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200898 vty_out(vty, " %ssdp audio-payload send-ptime%s",
899 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
900 vty_out(vty, " %ssdp audio-payload send-name%s",
901 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
902
903 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
904 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
905 else if (trunk->keepalive_interval)
906 vty_out(vty, " rtp keep-alive %d%s",
907 trunk->keepalive_interval, VTY_NEWLINE);
908 else
909 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200910 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200911 vty_out(vty, " force-realloc %d%s",
912 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200913 vty_out(vty, " rtp-accept-all %d%s",
914 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200915 if (trunk->omit_rtcp)
916 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
917 else
918 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100919 if (trunk->force_constant_ssrc || trunk->force_aligned_timing
Philipp Maierd19de2e2020-06-03 13:55:33 +0200920 || trunk->rfc5993_hr_convert) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200921 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200922 trunk->force_constant_ssrc ? "" : "no ",
923 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200924 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200925 trunk->force_aligned_timing ? "" : "no ",
926 VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100927 vty_out(vty, " %srtp-patch rfc5993hr%s",
928 trunk->rfc5993_hr_convert ? "" : "no ",
929 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200930 } else
931 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
932 if (trunk->audio_fmtp_extra)
933 vty_out(vty, " sdp audio fmtp-extra %s%s",
934 trunk->audio_fmtp_extra, VTY_NEWLINE);
935 vty_out(vty, " %sallow-transcoding%s",
936 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
937 }
938
939 return CMD_SUCCESS;
940}
941
942DEFUN(cfg_trunk_sdp_fmtp_extra,
943 cfg_trunk_sdp_fmtp_extra_cmd,
944 "sdp audio fmtp-extra .NAME",
945 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
946 "Extra Information\n")
947{
Philipp Maier14b27a82020-06-02 20:15:30 +0200948 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200949 char *txt = argv_concat(argv, argc, 0);
950 if (!txt)
951 return CMD_WARNING;
952
953 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
954 talloc_free(txt);
955 return CMD_SUCCESS;
956}
957
Philipp Maier7f90ddb2020-06-02 21:52:53 +0200958DEFUN_DEPRECATED(cfg_trunk_payload_number,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200959 cfg_trunk_payload_number_cmd,
960 "sdp audio-payload number <0-255>",
961 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
962{
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200963 return CMD_SUCCESS;
964}
965
966ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200967 "sdp audio payload number <0-255>",
968 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200969
Philipp Maier7f90ddb2020-06-02 21:52:53 +0200970DEFUN_DEPRECATED(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200971 cfg_trunk_payload_name_cmd,
972 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200973 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200974{
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200975 return CMD_SUCCESS;
976}
977
978ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200979 "sdp audio payload name NAME",
980 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200981
Philipp Maier21be42a2020-05-29 21:39:48 +0200982DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200983 cfg_trunk_loop_cmd,
984 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200985 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200986{
Philipp Maier14b27a82020-06-02 20:15:30 +0200987 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200988
989 if (g_cfg->osmux) {
990 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
991 return CMD_WARNING;
992 }
993 trunk->audio_loop = atoi(argv[0]);
994 return CMD_SUCCESS;
995}
996
997DEFUN(cfg_trunk_sdp_payload_send_ptime,
998 cfg_trunk_sdp_payload_send_ptime_cmd,
999 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001000 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001001{
Philipp Maier14b27a82020-06-02 20:15:30 +02001002 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001003 trunk->audio_send_ptime = 1;
1004 return CMD_SUCCESS;
1005}
1006
1007DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
1008 cfg_trunk_no_sdp_payload_send_ptime_cmd,
1009 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001010 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001011{
Philipp Maier14b27a82020-06-02 20:15:30 +02001012 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001013 trunk->audio_send_ptime = 0;
1014 return CMD_SUCCESS;
1015}
1016
1017DEFUN(cfg_trunk_sdp_payload_send_name,
1018 cfg_trunk_sdp_payload_send_name_cmd,
1019 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001020 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001021{
Philipp Maier14b27a82020-06-02 20:15:30 +02001022 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001023 trunk->audio_send_name = 1;
1024 return CMD_SUCCESS;
1025}
1026
1027DEFUN(cfg_trunk_no_sdp_payload_send_name,
1028 cfg_trunk_no_sdp_payload_send_name_cmd,
1029 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001030 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001031{
Philipp Maier14b27a82020-06-02 20:15:30 +02001032 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001033 trunk->audio_send_name = 0;
1034 return CMD_SUCCESS;
1035}
1036
Philipp Maier87bd9be2017-08-22 16:35:41 +02001037DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001038{
Philipp Maier14b27a82020-06-02 20:15:30 +02001039 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001040 trunk->omit_rtcp = 1;
1041 return CMD_SUCCESS;
1042}
1043
1044DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001045 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001046{
Philipp Maier14b27a82020-06-02 20:15:30 +02001047 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001048 trunk->omit_rtcp = 0;
1049 return CMD_SUCCESS;
1050}
1051
1052DEFUN(cfg_trunk_patch_rtp_ssrc,
1053 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001054 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001055{
Philipp Maier14b27a82020-06-02 20:15:30 +02001056 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001057 trunk->force_constant_ssrc = 1;
1058 return CMD_SUCCESS;
1059}
1060
1061DEFUN(cfg_trunk_no_patch_rtp_ssrc,
1062 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001063 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001064{
Philipp Maier14b27a82020-06-02 20:15:30 +02001065 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001066 trunk->force_constant_ssrc = 0;
1067 return CMD_SUCCESS;
1068}
1069
1070DEFUN(cfg_trunk_patch_rtp_ts,
1071 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001072 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001073{
Philipp Maier14b27a82020-06-02 20:15:30 +02001074 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001075 trunk->force_aligned_timing = 1;
1076 return CMD_SUCCESS;
1077}
1078
1079DEFUN(cfg_trunk_no_patch_rtp_ts,
1080 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001081 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001082{
Philipp Maier14b27a82020-06-02 20:15:30 +02001083 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001084 trunk->force_aligned_timing = 0;
1085 return CMD_SUCCESS;
1086}
1087
Philipp Maier9fc8a022019-02-20 12:26:52 +01001088DEFUN(cfg_trunk_patch_rtp_rfc5993hr,
1089 cfg_trunk_patch_rtp_rfc5993hr_cmd,
1090 "rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
1091{
Philipp Maier14b27a82020-06-02 20:15:30 +02001092 struct mgcp_trunk *trunk = vty->index;
Philipp Maier9fc8a022019-02-20 12:26:52 +01001093 trunk->rfc5993_hr_convert = true;
1094 return CMD_SUCCESS;
1095}
1096
1097DEFUN(cfg_trunk_no_patch_rtp_rfc5993hr,
1098 cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
1099 "no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
1100{
Philipp Maier14b27a82020-06-02 20:15:30 +02001101 struct mgcp_trunk *trunk = vty->index;
Philipp Maier9fc8a022019-02-20 12:26:52 +01001102 trunk->rfc5993_hr_convert = false;
1103 return CMD_SUCCESS;
1104}
1105
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001106DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001107 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001108{
Philipp Maier14b27a82020-06-02 20:15:30 +02001109 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001110 trunk->force_constant_ssrc = 0;
1111 trunk->force_aligned_timing = 0;
Philipp Maier9fc8a022019-02-20 12:26:52 +01001112 trunk->rfc5993_hr_convert = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001113 return CMD_SUCCESS;
1114}
1115
1116DEFUN(cfg_trunk_rtp_keepalive,
1117 cfg_trunk_rtp_keepalive_cmd,
1118 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001119 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001120{
Philipp Maier14b27a82020-06-02 20:15:30 +02001121 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001122 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
1123 return CMD_SUCCESS;
1124}
1125
1126DEFUN(cfg_trunk_rtp_keepalive_once,
1127 cfg_trunk_rtp_keepalive_once_cmd,
1128 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001129 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001130{
Philipp Maier14b27a82020-06-02 20:15:30 +02001131 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001132 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1133 return CMD_SUCCESS;
1134}
1135
1136DEFUN(cfg_trunk_no_rtp_keepalive,
1137 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001138 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001139{
Philipp Maier14b27a82020-06-02 20:15:30 +02001140 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001141 mgcp_trunk_set_keepalive(trunk, 0);
1142 return CMD_SUCCESS;
1143}
1144
1145DEFUN(cfg_trunk_allow_transcoding,
1146 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001147 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001148{
Philipp Maier14b27a82020-06-02 20:15:30 +02001149 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001150 trunk->no_audio_transcoding = 0;
1151 return CMD_SUCCESS;
1152}
1153
1154DEFUN(cfg_trunk_no_allow_transcoding,
1155 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001156 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001157{
Philipp Maier14b27a82020-06-02 20:15:30 +02001158 struct mgcp_trunk *trunk = vty->index;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001159 trunk->no_audio_transcoding = 1;
1160 return CMD_SUCCESS;
1161}
1162
Philipp Maier87bd9be2017-08-22 16:35:41 +02001163DEFUN(loop_conn,
1164 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001165 "loop-endpoint <0-64> NAME (0|1)",
1166 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001167 "The name in hex of the endpoint\n" "Disable the loop\n"
1168 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001169{
Philipp Maier14b27a82020-06-02 20:15:30 +02001170 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001171 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001172 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001173
Philipp Maierd19de2e2020-06-03 13:55:33 +02001174 trunk = mgcp_trunk_by_num(g_cfg, atoi(argv[0]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001175 if (!trunk) {
1176 vty_out(vty, "%%Trunk %d not found in the config.%s",
1177 atoi(argv[0]), VTY_NEWLINE);
1178 return CMD_WARNING;
1179 }
1180
1181 if (!trunk->endpoints) {
1182 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1183 trunk->trunk_nr, VTY_NEWLINE);
1184 return CMD_WARNING;
1185 }
1186
1187 int endp_no = strtoul(argv[1], NULL, 16);
1188 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1189 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001190 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001191 return CMD_WARNING;
1192 }
1193
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001194 endp = trunk->endpoints[endp_no];
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001195 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001196 llist_for_each_entry(conn, &endp->conns, entry) {
1197 if (conn->type == MGCP_CONN_TYPE_RTP)
1198 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1199 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1200 else {
1201 /* FIXME: Introduce support for other connection (E1)
1202 * types when implementation is available */
1203 vty_out(vty, "%%Can't enable SSRC patching,"
1204 "connection %s is not an RTP connection.%s",
1205 mgcp_conn_dump(conn), VTY_NEWLINE);
1206 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001207
Philipp Maier87bd9be2017-08-22 16:35:41 +02001208 if (loop)
1209 conn->mode = MGCP_CONN_LOOPBACK;
1210 else
1211 conn->mode = conn->mode_orig;
1212 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001213
1214 return CMD_SUCCESS;
1215}
1216
Philipp Maier87bd9be2017-08-22 16:35:41 +02001217DEFUN(tap_rtp,
1218 tap_rtp_cmd,
1219 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001220 "Forward data on endpoint to a different system\n" "Trunk number\n"
1221 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001222 "The connection id in hex\n"
1223 "Forward incoming data\n"
1224 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001225 "destination IP of the data\n" "destination port\n")
1226{
1227 struct mgcp_rtp_tap *tap;
Philipp Maier14b27a82020-06-02 20:15:30 +02001228 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001229 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001230 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001231 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001232
Philipp Maierd19de2e2020-06-03 13:55:33 +02001233 trunk = mgcp_trunk_by_num(g_cfg, atoi(argv[0]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001234 if (!trunk) {
1235 vty_out(vty, "%%Trunk %d not found in the config.%s",
1236 atoi(argv[0]), VTY_NEWLINE);
1237 return CMD_WARNING;
1238 }
1239
1240 if (!trunk->endpoints) {
1241 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1242 trunk->trunk_nr, VTY_NEWLINE);
1243 return CMD_WARNING;
1244 }
1245
1246 int endp_no = strtoul(argv[1], NULL, 16);
1247 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1248 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001249 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001250 return CMD_WARNING;
1251 }
1252
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001253 endp = trunk->endpoints[endp_no];
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001254
Philipp Maier01d24a32017-11-21 17:26:09 +01001255 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001256 conn = mgcp_conn_get_rtp(endp, conn_id);
1257 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001258 vty_out(vty, "Conn ID %s is invalid.%s",
1259 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001260 return CMD_WARNING;
1261 }
1262
1263 if (strcmp(argv[3], "in") == 0)
1264 tap = &conn->tap_in;
1265 else if (strcmp(argv[3], "out") == 0)
1266 tap = &conn->tap_out;
1267 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001268 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1269 return CMD_WARNING;
1270 }
1271
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001272 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001273 inet_aton(argv[4], &tap->forward.sin_addr);
1274 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001275 tap->enabled = 1;
1276 return CMD_SUCCESS;
1277}
1278
1279DEFUN(free_endp, free_endp_cmd,
1280 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001281 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001282{
Philipp Maier14b27a82020-06-02 20:15:30 +02001283 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001284 struct mgcp_endpoint *endp;
1285
Philipp Maierd19de2e2020-06-03 13:55:33 +02001286 trunk = mgcp_trunk_by_num(g_cfg, atoi(argv[0]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001287 if (!trunk) {
1288 vty_out(vty, "%%Trunk %d not found in the config.%s",
1289 atoi(argv[0]), VTY_NEWLINE);
1290 return CMD_WARNING;
1291 }
1292
1293 if (!trunk->endpoints) {
1294 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1295 trunk->trunk_nr, VTY_NEWLINE);
1296 return CMD_WARNING;
1297 }
1298
1299 int endp_no = strtoul(argv[1], NULL, 16);
1300 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1301 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001302 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001303 return CMD_WARNING;
1304 }
1305
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001306 endp = trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001307 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001308 return CMD_SUCCESS;
1309}
1310
1311DEFUN(reset_endp, reset_endp_cmd,
1312 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001313 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001314{
Philipp Maier14b27a82020-06-02 20:15:30 +02001315 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001316 struct mgcp_endpoint *endp;
1317 int endp_no, rc;
1318
Philipp Maierd19de2e2020-06-03 13:55:33 +02001319 trunk = mgcp_trunk_by_num(g_cfg, atoi(argv[0]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001320 if (!trunk) {
1321 vty_out(vty, "%%Trunk %d not found in the config.%s",
1322 atoi(argv[0]), VTY_NEWLINE);
1323 return CMD_WARNING;
1324 }
1325
1326 if (!trunk->endpoints) {
1327 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1328 trunk->trunk_nr, VTY_NEWLINE);
1329 return CMD_WARNING;
1330 }
1331
1332 endp_no = strtoul(argv[1], NULL, 16);
1333 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1334 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001335 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001336 return CMD_WARNING;
1337 }
1338
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001339 endp = trunk->endpoints[endp_no];
1340 rc = mgcp_send_reset_ep(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001341 if (rc < 0) {
1342 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1343 return CMD_WARNING;
1344 }
1345 return CMD_SUCCESS;
1346}
1347
1348DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001349 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001350{
1351 int rc;
1352
1353 rc = mgcp_send_reset_all(g_cfg);
1354 if (rc < 0) {
1355 vty_out(vty, "Error %d during endpoint reset.%s",
1356 rc, VTY_NEWLINE);
1357 return CMD_WARNING;
1358 }
1359 return CMD_SUCCESS;
1360}
1361
1362#define OSMUX_STR "RTP multiplexing\n"
1363DEFUN(cfg_mgcp_osmux,
1364 cfg_mgcp_osmux_cmd,
1365 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001366 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001367{
Philipp Maierd19de2e2020-06-03 13:55:33 +02001368 struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_VIRT_TRUNK_ID);
1369 OSMO_ASSERT(trunk);
1370
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001371 if (strcmp(argv[0], "off") == 0) {
1372 g_cfg->osmux = OSMUX_USAGE_OFF;
1373 return CMD_SUCCESS;
Pau Espin Pedrolb542b042019-04-23 13:09:32 +02001374 } else if (strcmp(argv[0], "on") == 0)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001375 g_cfg->osmux = OSMUX_USAGE_ON;
1376 else if (strcmp(argv[0], "only") == 0)
1377 g_cfg->osmux = OSMUX_USAGE_ONLY;
1378
Philipp Maierd19de2e2020-06-03 13:55:33 +02001379 if (trunk->audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001380 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001381 return CMD_WARNING;
1382 }
1383
1384 return CMD_SUCCESS;
Pau Espin Pedrolb542b042019-04-23 13:09:32 +02001385
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001386}
1387
1388DEFUN(cfg_mgcp_osmux_ip,
1389 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001390 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001391{
1392 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1393 return CMD_SUCCESS;
1394}
1395
1396DEFUN(cfg_mgcp_osmux_batch_factor,
1397 cfg_mgcp_osmux_batch_factor_cmd,
1398 "osmux batch-factor <1-8>",
1399 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1400{
1401 g_cfg->osmux_batch = atoi(argv[0]);
1402 return CMD_SUCCESS;
1403}
1404
1405DEFUN(cfg_mgcp_osmux_batch_size,
1406 cfg_mgcp_osmux_batch_size_cmd,
1407 "osmux batch-size <1-65535>",
1408 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1409{
1410 g_cfg->osmux_batch_size = atoi(argv[0]);
1411 return CMD_SUCCESS;
1412}
1413
1414DEFUN(cfg_mgcp_osmux_port,
1415 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001416 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001417{
1418 g_cfg->osmux_port = atoi(argv[0]);
1419 return CMD_SUCCESS;
1420}
1421
1422DEFUN(cfg_mgcp_osmux_dummy,
1423 cfg_mgcp_osmux_dummy_cmd,
1424 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001425 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1426 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001427{
1428 if (strcmp(argv[0], "on") == 0)
1429 g_cfg->osmux_dummy = 1;
1430 else if (strcmp(argv[0], "off") == 0)
1431 g_cfg->osmux_dummy = 0;
1432
1433 return CMD_SUCCESS;
1434}
1435
Philipp Maier12943ea2018-01-17 15:40:25 +01001436DEFUN(cfg_mgcp_domain,
1437 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001438 "domain NAME",
1439 "Set the domain part expected in MGCP messages' endpoint names\n"
1440 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001441{
1442 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1443 return CMD_SUCCESS;
1444}
1445
Oliver Smithe36b7752019-01-22 16:31:36 +01001446DEFUN(cfg_mgcp_conn_timeout,
1447 cfg_mgcp_conn_timeout_cmd,
Oliver Smithd2ce4442019-06-26 09:56:44 +02001448 "conn-timeout <0-65534>",
1449 "Set a time after which inactive connections (CIs) are closed. Set to 0 to disable timeout. This can be used to"
1450 " work around interoperability problems causing connections to stay open forever, and slowly exhausting all"
Oliver Smith189f29e2019-06-26 12:08:20 +02001451 " available ports. Enable keep-alive packets in MGW clients when using this option together with LCLS (OsmoBSC,"
1452 " OsmoMSC: 'rtp keep-alive')!\n"
Oliver Smithe36b7752019-01-22 16:31:36 +01001453 "Timeout value (sec.)\n")
1454{
1455 g_cfg->conn_timeout = strtoul(argv[0], NULL, 10);
1456 return CMD_SUCCESS;
1457}
1458
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001459int mgcp_vty_init(void)
1460{
1461 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001462 install_element_ve(&show_mgcp_endpoint_cmd);
1463 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001464 install_element(ENABLE_NODE, &loop_conn_cmd);
1465 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001466 install_element(ENABLE_NODE, &free_endp_cmd);
1467 install_element(ENABLE_NODE, &reset_endp_cmd);
1468 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1469
1470 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1471 install_node(&mgcp_node, config_write_mgcp);
1472
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001473 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001474 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1475 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1476 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001477 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001478 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001479 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001480 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001481 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001482 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001483 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1484 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001485 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1486 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1487 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1488 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1489 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1490 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1491 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1492 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1493 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001494 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1495 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1496 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1497 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1498 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1499 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001500 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001501 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1502 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1503 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1504 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1505 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1506 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1507 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1508 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
Philipp Maier9fc8a022019-02-20 12:26:52 +01001509 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_rfc5993hr_cmd);
1510 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_rfc5993hr_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001511 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1512 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1513 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1514 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1515 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1516 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1517 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1518 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1519 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1520 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1521 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1522 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1523 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001524 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Oliver Smithe36b7752019-01-22 16:31:36 +01001525 install_element(MGCP_NODE, &cfg_mgcp_conn_timeout_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001526
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001527 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1528 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001529 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1530 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1531 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1532 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1533 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1534 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1535 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1536 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1537 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1538 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1539 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1540 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1541 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
Philipp Maier9fc8a022019-02-20 12:26:52 +01001542 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_rfc5993hr_cmd);
1543 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_rfc5993hr_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001544 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1545 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1546 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1547 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1548 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1549 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1550 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1551 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1552 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1553
1554 return 0;
1555}
1556
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001557int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1558 enum mgcp_role role)
1559{
1560 int rc;
Philipp Maier14b27a82020-06-02 20:15:30 +02001561 struct mgcp_trunk *trunk;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001562
1563 cfg->osmux_port = OSMUX_PORT;
1564 cfg->osmux_batch = 4;
1565 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1566
1567 g_cfg = cfg;
1568 rc = vty_read_config_file(config_file, NULL);
1569 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001570 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1571 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001572 return rc;
1573 }
1574
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001575 if (!g_cfg->source_addr) {
1576 fprintf(stderr, "You need to specify a bind address.\n");
1577 return -1;
1578 }
1579
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001580 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maierc66ab2c2020-06-02 20:55:34 +02001581 if (mgcp_trunk_alloc_endpts(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001582 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001583 "Failed to initialize trunk %d (%d endpoints)\n",
1584 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001585 return -1;
1586 }
1587 }
1588 cfg->role = role;
1589
1590 return 0;
1591}