158 lines
4.8 KiB
C
158 lines
4.8 KiB
C
/* Filter/overlay bearer service selections across MS, RAN and CN limitations */
|
|
/*
|
|
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
|
* All Rights Reserved
|
|
*
|
|
* Author: Oliver Smith
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0+
|
|
*
|
|
* 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/>.
|
|
*/
|
|
|
|
#include <osmocom/mgcp_client/mgcp_client.h>
|
|
|
|
#include <osmocom/msc/csd_filter.h>
|
|
|
|
static void add_all_geran_bs(struct csd_bs_list *list)
|
|
{
|
|
/* See 3GPP TS 122.002 Bearer Services */
|
|
/* In order of preference. TODO: make configurable */
|
|
|
|
/* GSM-R */
|
|
csd_bs_list_add_bs(list, CSD_BS_24_T_V110_2k4);
|
|
csd_bs_list_add_bs(list, CSD_BS_25_T_V110_4k8);
|
|
csd_bs_list_add_bs(list, CSD_BS_26_T_V110_9k6);
|
|
|
|
/* Other */
|
|
csd_bs_list_add_bs(list, CSD_BS_21_T_V110_0k3);
|
|
csd_bs_list_add_bs(list, CSD_BS_22_T_V110_1k2);
|
|
csd_bs_list_add_bs(list, CSD_BS_21_NT_V110_0k3);
|
|
csd_bs_list_add_bs(list, CSD_BS_22_NT_V110_1k2);
|
|
csd_bs_list_add_bs(list, CSD_BS_24_NT_V110_2k4);
|
|
csd_bs_list_add_bs(list, CSD_BS_25_NT_V110_4k8);
|
|
csd_bs_list_add_bs(list, CSD_BS_26_NT_V110_9k6);
|
|
csd_bs_list_add_bs(list, CSD_BS_31_T_V110_1k2);
|
|
csd_bs_list_add_bs(list, CSD_BS_32_T_V110_2k4);
|
|
csd_bs_list_add_bs(list, CSD_BS_33_T_V110_4k8);
|
|
csd_bs_list_add_bs(list, CSD_BS_34_T_V110_9k6);
|
|
}
|
|
|
|
static void add_all_utran_bs(struct csd_bs_list *list)
|
|
{
|
|
/* See 3GPP TS 122.002 Bearer Services */
|
|
/* In order of preference. TODO: make configurable */
|
|
csd_bs_list_add_bs(list, CSD_BS_21_NT_V110_0k3);
|
|
csd_bs_list_add_bs(list, CSD_BS_22_NT_V110_1k2);
|
|
csd_bs_list_add_bs(list, CSD_BS_24_NT_V110_2k4);
|
|
csd_bs_list_add_bs(list, CSD_BS_25_NT_V110_4k8);
|
|
csd_bs_list_add_bs(list, CSD_BS_26_NT_V110_9k6);
|
|
}
|
|
|
|
void csd_filter_set_ran(struct csd_filter *filter, enum osmo_rat_type ran_type)
|
|
{
|
|
filter->ran = (struct csd_bs_list){};
|
|
|
|
switch (ran_type) {
|
|
default:
|
|
case OSMO_RAT_GERAN_A:
|
|
add_all_geran_bs(&filter->ran);
|
|
break;
|
|
case OSMO_RAT_UTRAN_IU:
|
|
add_all_utran_bs(&filter->ran);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int csd_filter_run(struct csd_filter *filter, struct sdp_msg *result, const struct sdp_msg *remote)
|
|
{
|
|
struct csd_bs_list *r = &result->bearer_services;
|
|
enum csd_bs a = filter->assignment;
|
|
|
|
*r = filter->ran;
|
|
|
|
if (filter->ms.count)
|
|
csd_bs_list_intersection(r, &filter->ms);
|
|
if (filter->bss.count)
|
|
csd_bs_list_intersection(r, &filter->bss);
|
|
if (remote->bearer_services.count)
|
|
csd_bs_list_intersection(r, &remote->bearer_services);
|
|
|
|
/* Future: If osmo-msc were able to trigger a re-assignment [...] see
|
|
* comment in codec_filter_run(). */
|
|
|
|
if (a) {
|
|
*r = (struct csd_bs_list){};
|
|
csd_bs_list_add_bs(r, a);
|
|
}
|
|
|
|
result->audio_codecs.count = 1;
|
|
result->audio_codecs.codec[0] = (struct sdp_audio_codec){
|
|
.payload_type = CODEC_CLEARMODE,
|
|
.subtype_name = "CLEARMODE",
|
|
.rate = 8000,
|
|
};
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int csd_filter_to_str_buf(char *buf, size_t buflen, const struct csd_filter *filter,
|
|
const struct sdp_msg *result, const struct sdp_msg *remote)
|
|
{
|
|
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
|
|
OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, result);
|
|
OSMO_STRBUF_PRINTF(sb, " (from:");
|
|
|
|
if (filter->assignment) {
|
|
OSMO_STRBUF_PRINTF(sb, " assigned=");
|
|
OSMO_STRBUF_APPEND(sb, csd_bs_to_str_buf, filter->assignment);
|
|
}
|
|
|
|
if (remote->bearer_services.count || osmo_sockaddr_str_is_nonzero(&remote->rtp)) {
|
|
OSMO_STRBUF_PRINTF(sb, " remote=");
|
|
OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, remote);
|
|
}
|
|
|
|
if (filter->ms.count) {
|
|
OSMO_STRBUF_PRINTF(sb, " MS={");
|
|
OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &filter->ms);
|
|
OSMO_STRBUF_PRINTF(sb, "}");
|
|
}
|
|
|
|
if (filter->bss.count) {
|
|
OSMO_STRBUF_PRINTF(sb, " bss={");
|
|
OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &filter->bss);
|
|
OSMO_STRBUF_PRINTF(sb, "}");
|
|
}
|
|
|
|
OSMO_STRBUF_PRINTF(sb, " RAN={");
|
|
OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &filter->ran);
|
|
OSMO_STRBUF_PRINTF(sb, "}");
|
|
|
|
OSMO_STRBUF_PRINTF(sb, ")");
|
|
|
|
return sb.chars_needed;
|
|
}
|
|
|
|
char *csd_filter_to_str_c(void *ctx, const struct csd_filter *filter, const struct sdp_msg *result, const struct sdp_msg *remote)
|
|
{
|
|
OSMO_NAME_C_IMPL(ctx, 128, "csd_filter_to_str_c-ERROR", csd_filter_to_str_buf, filter, result, remote)
|
|
}
|
|
|
|
const char *csd_filter_to_str(const struct csd_filter *filter, const struct sdp_msg *result, const struct sdp_msg *remote)
|
|
{
|
|
return csd_filter_to_str_c(OTC_SELECT, filter, result, remote);
|
|
}
|