/* Filter/overlay bearer service selections across MS, RAN and CN limitations */ /* * (C) 2023 by sysmocom - s.f.m.c. GmbH * 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 . */ #include #include 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); }