osmo-bsc: Negotiate rtp ip address/port with BTS
This patch adds the support for the RTP IP-Address/Port assignment. The post communicated via the assignment request is now transmitted via RSL/IPACC to the BTS. The Response containing the RX-Port at the BTS side is communicated back to the MSC. Since we plan to add a private MGCPGW to each BSC, this has to be extended. Currently it only creates a direct connection to the BTS. This will be introduced with a future patch. Change-Id: I693e428b6bfdd8534eb5b88fa4d47dac20db88ea
This commit is contained in:
parent
38b3f767e5
commit
4599007a41
|
@ -252,6 +252,16 @@ struct gsm_lchan {
|
|||
uint8_t speech_mode;
|
||||
#ifdef ROLE_BSC
|
||||
struct rtp_socket *rtp_socket;
|
||||
|
||||
/* info we need to postpone the AoIP
|
||||
* assignment completed message */
|
||||
struct {
|
||||
uint8_t rr_cause;
|
||||
uint8_t chosen_channel;
|
||||
uint8_t encr_alg_id;
|
||||
uint8_t speech_mode;
|
||||
bool valid;
|
||||
} ass_compl;
|
||||
#else
|
||||
struct osmo_rtp_socket *rtp_socket;
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@ struct osmo_bsc_sccp_con {
|
|||
|
||||
/* for audio handling */
|
||||
uint16_t cic;
|
||||
uint32_t rtp_ip;
|
||||
int rtp_port;
|
||||
|
||||
/* for advanced ping/pong */
|
||||
|
|
|
@ -435,11 +435,28 @@ static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_
|
|||
struct msgb *resp;
|
||||
return_when_not_connected(conn);
|
||||
|
||||
LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN COMPL\n");
|
||||
if (is_ipaccess_bts(conn->bts) && conn->sccp_con->rtp_ip) {
|
||||
/* NOTE: In a network that makes use of an IPA base station
|
||||
* and AoIP, we have to wait until the BTS reports its RTP
|
||||
* IP/Port combination back to BSC via RSL. Unfortunately, the
|
||||
* IPA protocol sends its Abis assignment complete message
|
||||
* before it sends its RTP IP/Port via IPACC. So we will now
|
||||
* postpone the AoIP assignment completed message until we
|
||||
* know the RTP IP/Port combination. */
|
||||
LOGP(DMSC, LOGL_INFO, "POSTPONE MSC ASSIGN COMPL\n");
|
||||
conn->lchan->abis_ip.ass_compl.rr_cause = rr_cause;
|
||||
conn->lchan->abis_ip.ass_compl.chosen_channel = chosen_channel;
|
||||
conn->lchan->abis_ip.ass_compl.encr_alg_id = encr_alg_id;
|
||||
conn->lchan->abis_ip.ass_compl.speech_mode = speech_model;
|
||||
conn->lchan->abis_ip.ass_compl.valid = true;
|
||||
|
||||
resp = gsm0808_create_assignment_completed(rr_cause, chosen_channel,
|
||||
encr_alg_id, speech_model);
|
||||
queue_msg_or_return(resp);
|
||||
} else {
|
||||
/* NOTE: Send the A assignment complete message immediately. */
|
||||
LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN COMPL\n");
|
||||
resp = gsm0808_create_assignment_completed(rr_cause, chosen_channel,
|
||||
encr_alg_id, speech_model);
|
||||
queue_msg_or_return(resp);
|
||||
}
|
||||
}
|
||||
|
||||
static void bsc_assign_fail(struct gsm_subscriber_connection *conn,
|
||||
|
|
|
@ -26,15 +26,52 @@
|
|||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <osmocom/gsm/gsm0808.h>
|
||||
#include <openbsc/osmo_bsc_sigtran.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* Generate and send assignment complete message */
|
||||
static int send_aoip_ass_compl(struct gsm_subscriber_connection *conn, struct gsm_lchan *lchan)
|
||||
{
|
||||
struct msgb *resp;
|
||||
struct sockaddr_storage rtp_addr;
|
||||
struct sockaddr_in rtp_addr_in;
|
||||
|
||||
OSMO_ASSERT(lchan->abis_ip.ass_compl.valid == true);
|
||||
|
||||
/* Package RTP-Address data */
|
||||
memset(&rtp_addr_in, 0, sizeof(rtp_addr_in));
|
||||
rtp_addr_in.sin_family = AF_INET;
|
||||
rtp_addr_in.sin_port = htons(lchan->abis_ip.bound_port);
|
||||
rtp_addr_in.sin_addr.s_addr = htonl(lchan->abis_ip.bound_ip);
|
||||
memset(&rtp_addr, 0, sizeof(rtp_addr));
|
||||
memcpy(&rtp_addr, &rtp_addr_in, sizeof(rtp_addr_in));
|
||||
|
||||
/* Generate message */
|
||||
resp = gsm0808_create_ass_compl(lchan->abis_ip.ass_compl.rr_cause,
|
||||
lchan->abis_ip.ass_compl.chosen_channel,
|
||||
lchan->abis_ip.ass_compl.encr_alg_id,
|
||||
lchan->abis_ip.ass_compl.speech_mode,
|
||||
&rtp_addr,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Failed to generate assignment completed message!\n"); \
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return osmo_bsc_sigtran_send(conn->sccp_con, resp);
|
||||
}
|
||||
|
||||
static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct gsm_subscriber_connection *con;
|
||||
struct gsm_lchan *lchan = signal_data;
|
||||
int rc;
|
||||
uint32_t rtp_ip;
|
||||
|
||||
if (subsys != SS_ABISIP)
|
||||
return 0;
|
||||
|
@ -49,11 +86,19 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
|
|||
* TODO: handle handover here... then the audio should go to
|
||||
* the old mgcp port..
|
||||
*/
|
||||
|
||||
/* we can ask it to connect now */
|
||||
LOGP(DMSC, LOGL_DEBUG, "Connecting BTS to port: %d conn: %d\n",
|
||||
con->sccp_con->rtp_port, lchan->abis_ip.conn_id);
|
||||
|
||||
rc = rsl_ipacc_mdcx(lchan, ntohl(INADDR_ANY),
|
||||
/* If AoIP is in use, the rtp_ip, which has been communicated
|
||||
* via the A interface as connect_ip */
|
||||
if(con->sccp_con->rtp_ip)
|
||||
rtp_ip = con->sccp_con->rtp_ip;
|
||||
else
|
||||
rtp_ip = ntohl(INADDR_ANY);
|
||||
|
||||
rc = rsl_ipacc_mdcx(lchan, rtp_ip,
|
||||
con->sccp_con->rtp_port,
|
||||
lchan->abis_ip.rtp_payload2);
|
||||
if (rc < 0) {
|
||||
|
@ -61,6 +106,18 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
|
|||
return rc;
|
||||
}
|
||||
break;
|
||||
|
||||
case S_ABISIP_MDCX_ACK:
|
||||
if (is_ipaccess_bts(con->bts) && con->sccp_con->rtp_ip) {
|
||||
/* NOTE: This is only relevant on AoIP networks with
|
||||
* IPA based base stations. See also osmo_bsc_api.c,
|
||||
* function bsc_assign_compl() */
|
||||
LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN COMPL (POSTPONED)\n");
|
||||
if (send_aoip_ass_compl(con, lchan) != 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,7 +29,11 @@
|
|||
|
||||
#include <osmocom/gsm/protocol/gsm_08_08.h>
|
||||
#include <osmocom/gsm/gsm0808.h>
|
||||
#include <osmocom/gsm/gsm0808_utils.h>
|
||||
#include <openbsc/osmo_bsc_sigtran.h>
|
||||
#include <osmocom/core/byteswap.h>
|
||||
|
||||
#define IP_V4_ADDR_LEN 4
|
||||
|
||||
/*
|
||||
* helpers for the assignment command
|
||||
|
@ -305,10 +309,14 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
|
|||
struct bsc_msc_data *msc;
|
||||
struct tlv_parsed tp;
|
||||
uint8_t *data;
|
||||
uint8_t timeslot;
|
||||
uint8_t multiplex;
|
||||
uint8_t timeslot = 0;
|
||||
uint8_t multiplex = 0;
|
||||
enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
|
||||
int i, supported, port, full_rate = -1;
|
||||
bool aoip = false;
|
||||
struct sockaddr_storage rtp_addr;
|
||||
struct sockaddr_in *rtp_addr_in;
|
||||
int rc;
|
||||
|
||||
if (!conn->conn) {
|
||||
LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
|
||||
|
@ -322,15 +330,25 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
|
|||
goto reject;
|
||||
}
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n");
|
||||
/* Detect if a CIC code is present, if so, we use the classic ip.access
|
||||
* method to calculate the RTP port */
|
||||
if (TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
|
||||
conn->cic = osmo_load16be(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
|
||||
timeslot = conn->cic & 0x1f;
|
||||
multiplex = (conn->cic & ~0x1f) >> 5;
|
||||
} else if(TLVP_PRESENT(&tp, GSM0808_IE_AOIP_TRASP_ADDR)) {
|
||||
/* Decode AoIP transport address element */
|
||||
rc = gsm0808_dec_aoip_trasp_addr(&rtp_addr, TLVP_VAL(&tp, GSM0808_IE_AOIP_TRASP_ADDR), TLVP_LEN(&tp, GSM0808_IE_AOIP_TRASP_ADDR));
|
||||
if (rc < 0) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Unable to decode aoip transport address.\n");
|
||||
goto reject;
|
||||
}
|
||||
aoip = true;
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_ERROR, "transport address missing. Audio routing will not work.\n");
|
||||
goto reject;
|
||||
}
|
||||
|
||||
conn->cic = osmo_load16be(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
|
||||
timeslot = conn->cic & 0x1f;
|
||||
multiplex = (conn->cic & ~0x1f) >> 5;
|
||||
|
||||
/*
|
||||
* Currently we only support a limited subset of all
|
||||
* possible channel types. The limitation ends by not using
|
||||
|
@ -383,9 +401,25 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
|
|||
goto reject;
|
||||
}
|
||||
|
||||
/* map it to a MGCP Endpoint and a RTP port */
|
||||
port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
|
||||
conn->rtp_port = rtp_calculate_port(port, msc->rtp_base);
|
||||
if (aoip == false) {
|
||||
/* map it to a MGCP Endpoint and a RTP port */
|
||||
port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
|
||||
conn->rtp_port = rtp_calculate_port(port, msc->rtp_base);
|
||||
conn->rtp_ip = 0;
|
||||
} else {
|
||||
/* use address / port supplied with the AoIP
|
||||
* transport address element */
|
||||
if(rtp_addr.ss_family == AF_INET)
|
||||
{
|
||||
rtp_addr_in = (struct sockaddr_in *)&rtp_addr;
|
||||
conn->rtp_port = osmo_ntohs(rtp_addr_in->sin_port);
|
||||
memcpy(&conn->rtp_ip, &rtp_addr_in->sin_addr.s_addr, IP_V4_ADDR_LEN);
|
||||
conn->rtp_ip = osmo_ntohl(conn->rtp_ip);
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_ERROR, "Unsopported addressing scheme. (supports only IPV4)\n");
|
||||
goto reject;
|
||||
}
|
||||
}
|
||||
|
||||
return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
|
||||
|
||||
|
|
Loading…
Reference in New Issue