osmux: Support local CID != remote CID
So far the implementation only allowed the remote CID being the same as the one dynamically implemented internally. Related: SYS#6138 Change-Id: I6b03eabc0305580c9788c529bec7dda9044a008f
This commit is contained in:
parent
87f114a1d0
commit
2177919edb
|
@ -80,10 +80,14 @@ struct mgcp_conn_rtp {
|
|||
struct {
|
||||
/* Osmux state: disabled, activating, active */
|
||||
enum osmux_state state;
|
||||
/* Is cid holding valid data? is it allocated from pool? */
|
||||
bool cid_allocated;
|
||||
/* Allocated Osmux circuit ID for this conn */
|
||||
uint8_t cid;
|
||||
/* Is local_cid holding valid data? is it allocated from pool? */
|
||||
bool local_cid_allocated;
|
||||
/* Allocated local Osmux circuit ID for this conn */
|
||||
uint8_t local_cid;
|
||||
/* Is remote_cid holding valid data? was it already received from client? */
|
||||
bool remote_cid_present;
|
||||
/* Received remote Osmux circuit ID for this conn */
|
||||
uint8_t remote_cid;
|
||||
/* handle to batch messages, shared (refcounted) among several conns */
|
||||
struct osmux_in_handle *in;
|
||||
/* handle to unbatch messages, one allocated and owned per conn */
|
||||
|
|
|
@ -17,8 +17,8 @@ int osmux_init(int role, struct mgcp_trunk *trunk);
|
|||
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
|
||||
const struct osmo_sockaddr *addr);
|
||||
void conn_osmux_disable(struct mgcp_conn_rtp *conn);
|
||||
int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid);
|
||||
void conn_osmux_release_cid(struct mgcp_conn_rtp *conn);
|
||||
int conn_osmux_allocate_local_cid(struct mgcp_conn_rtp *conn);
|
||||
void conn_osmux_release_local_cid(struct mgcp_conn_rtp *conn);
|
||||
int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn);
|
||||
int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
|
||||
|
||||
|
|
|
@ -95,8 +95,10 @@ static int mgcp_rtp_conn_init(struct mgcp_conn_rtp *conn_rtp, struct mgcp_conn *
|
|||
static atomic_uint rate_ctr_index = 0;
|
||||
|
||||
conn_rtp->type = MGCP_RTP_DEFAULT;
|
||||
conn_rtp->osmux.cid_allocated = false;
|
||||
conn_rtp->osmux.cid = 0;
|
||||
conn_rtp->osmux.local_cid_allocated = false;
|
||||
conn_rtp->osmux.local_cid = 0;
|
||||
conn_rtp->osmux.remote_cid_present = false;
|
||||
conn_rtp->osmux.remote_cid = 0;
|
||||
|
||||
/* backpointer to the generic part of the connection */
|
||||
conn->u.rtp.conn = conn;
|
||||
|
|
|
@ -210,7 +210,7 @@ int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn)
|
|||
|
||||
if (conn->osmux.state != OSMUX_STATE_ENABLED) {
|
||||
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO, "forwarding RTP to Osmux conn not yet enabled, dropping (cid=%d)\n",
|
||||
conn->osmux.cid);
|
||||
conn->osmux.remote_cid);
|
||||
rtpconn_rate_ctr_inc(conn, conn->conn->endp, OSMUX_DROPPED_AMR_PAYLOADS_CTR);
|
||||
return -1;
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn)
|
|||
memcpy(msg->data, buf, buf_len);
|
||||
msgb_put(msg, buf_len);
|
||||
|
||||
while ((ret = osmux_xfrm_input(conn->osmux.in, msg, conn->osmux.cid)) > 0) {
|
||||
while ((ret = osmux_xfrm_input(conn->osmux.in, msg, conn->osmux.remote_cid)) > 0) {
|
||||
/* batch full, build and deliver it */
|
||||
osmux_xfrm_input_deliver(conn->osmux.in);
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn)
|
|||
|
||||
/* Lookup the endpoint that corresponds to the specified address (port) */
|
||||
static struct mgcp_conn_rtp*
|
||||
osmux_conn_lookup(struct mgcp_trunk *trunk, uint8_t cid, const struct osmo_sockaddr *rem_addr)
|
||||
osmux_conn_lookup(struct mgcp_trunk *trunk, uint8_t local_cid, const struct osmo_sockaddr *rem_addr)
|
||||
{
|
||||
struct mgcp_endpoint *endp;
|
||||
struct mgcp_conn *conn = NULL;
|
||||
|
@ -252,13 +252,13 @@ osmux_conn_lookup(struct mgcp_trunk *trunk, uint8_t cid, const struct osmo_socka
|
|||
|
||||
/* FIXME: Match remote address! */
|
||||
|
||||
if (conn_rtp->osmux.cid == cid)
|
||||
if (conn_rtp->osmux.local_cid == local_cid)
|
||||
return conn_rtp;
|
||||
}
|
||||
}
|
||||
|
||||
LOGP(DOSMUX, LOGL_ERROR, "Cannot find osmux conn with rem_addr=%s cid=%d\n",
|
||||
osmo_sockaddr_to_str(rem_addr), cid);
|
||||
LOGP(DOSMUX, LOGL_ERROR, "Cannot find osmux conn with rem_addr=%s local_cid=%d\n",
|
||||
osmo_sockaddr_to_str(rem_addr), local_cid);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -327,7 +327,8 @@ static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_r
|
|||
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO,
|
||||
"Osmux %s CID %u towards %s is now enabled\n",
|
||||
sending ? "sent" : "received",
|
||||
conn->osmux.cid, osmo_sockaddr_to_str(&rem_addr));
|
||||
sending ? conn->osmux.remote_cid : conn->osmux.local_cid,
|
||||
osmo_sockaddr_to_str(&rem_addr));
|
||||
return 0;
|
||||
case OSMUX_STATE_ENABLED:
|
||||
return 0;
|
||||
|
@ -517,16 +518,16 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
|
|||
mgcp_conn_dump(conn->conn));
|
||||
return -1;
|
||||
}
|
||||
if (osmux_xfrm_input_open_circuit(conn->osmux.in, conn->osmux.cid, osmux_dummy) < 0) {
|
||||
if (osmux_xfrm_input_open_circuit(conn->osmux.in, conn->osmux.remote_cid, osmux_dummy) < 0) {
|
||||
LOGPCONN(conn->conn, DOSMUX, LOGL_ERROR,
|
||||
"Cannot open osmux circuit %u for conn:%s\n",
|
||||
conn->osmux.cid, mgcp_conn_dump(conn->conn));
|
||||
conn->osmux.remote_cid, mgcp_conn_dump(conn->conn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->osmux.out = osmux_xfrm_output_alloc(conn->conn);
|
||||
osmux_xfrm_output_set_rtp_ssrc(conn->osmux.out,
|
||||
(conn->osmux.cid * rtp_ssrc_winlen) +
|
||||
(conn->osmux.remote_cid * rtp_ssrc_winlen) +
|
||||
(random() % rtp_ssrc_winlen));
|
||||
osmux_xfrm_output_set_rtp_pl_type(conn->osmux.out, conn->end.codec->payload_type);
|
||||
osmux_xfrm_output_set_tx_cb(conn->osmux.out,
|
||||
|
@ -547,7 +548,7 @@ void conn_osmux_disable(struct mgcp_conn_rtp *conn)
|
|||
OSMO_ASSERT(conn->osmux.state != OSMUX_STATE_DISABLED);
|
||||
|
||||
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO,
|
||||
"Releasing connection using Osmux CID %u\n", conn->osmux.cid);
|
||||
"Releasing connection using local Osmux CID %u\n", conn->osmux.local_cid);
|
||||
|
||||
struct rate_ctr_group *all_osmux_stats = conn->conn->endp->trunk->ratectr.all_osmux_conn_stats;
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(all_osmux_stats, OSMUX_NUM_CONNECTIONS));
|
||||
|
@ -557,53 +558,44 @@ void conn_osmux_disable(struct mgcp_conn_rtp *conn)
|
|||
osmux_xfrm_output_set_tx_cb(conn->osmux.out, NULL, NULL);
|
||||
TALLOC_FREE(conn->osmux.out);
|
||||
|
||||
osmux_xfrm_input_close_circuit(conn->osmux.in, conn->osmux.cid);
|
||||
osmux_xfrm_input_close_circuit(conn->osmux.in, conn->osmux.remote_cid);
|
||||
conn->osmux.state = OSMUX_STATE_DISABLED;
|
||||
osmux_handle_put(conn->osmux.in);
|
||||
conn->osmux.remote_cid = 0;
|
||||
conn->osmux.remote_cid_present = false;
|
||||
|
||||
rate_ctr_group_free(conn->osmux.ctrg);
|
||||
conn->osmux.ctrg = NULL;
|
||||
}
|
||||
conn_osmux_release_cid(conn);
|
||||
conn_osmux_release_local_cid(conn);
|
||||
}
|
||||
|
||||
/*! relase OSXMUX cid, that had been allocated to this connection.
|
||||
* \param[in] conn connection with OSMUX cid to release */
|
||||
void conn_osmux_release_cid(struct mgcp_conn_rtp *conn)
|
||||
void conn_osmux_release_local_cid(struct mgcp_conn_rtp *conn)
|
||||
{
|
||||
if (conn->osmux.cid_allocated)
|
||||
osmux_cid_pool_put(conn->osmux.cid);
|
||||
conn->osmux.cid = 0;
|
||||
conn->osmux.cid_allocated = false;
|
||||
if (conn->osmux.local_cid_allocated)
|
||||
osmux_cid_pool_put(conn->osmux.local_cid);
|
||||
conn->osmux.local_cid = 0;
|
||||
conn->osmux.local_cid_allocated = false;
|
||||
}
|
||||
|
||||
/*! allocate OSXMUX cid to connection.
|
||||
* \param[in] conn connection for which we allocate the OSMUX cid
|
||||
* \param[in] osmux_cid OSMUX cid to allocate. -1 Means take next available one.
|
||||
* \returns Allocated OSMUX cid, -1 on error (no free cids avail, or selected one is already taken).
|
||||
/*! allocate local OSMUX cid to connection.
|
||||
* \param[in] conn connection for which we allocate the local OSMUX cid
|
||||
* \returns Allocated OSMUX cid, -1 on error (no free CIDs avail).
|
||||
*/
|
||||
int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid)
|
||||
int conn_osmux_allocate_local_cid(struct mgcp_conn_rtp *conn)
|
||||
{
|
||||
if (osmux_cid != -1 && osmux_cid_pool_allocated((uint8_t) osmux_cid)) {
|
||||
OSMO_ASSERT(conn->osmux.local_cid_allocated == false);
|
||||
int osmux_cid = osmux_cid_pool_get_next();
|
||||
if (osmux_cid == -1) {
|
||||
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO,
|
||||
"Osmux CID %d already allocated!\n",
|
||||
osmux_cid);
|
||||
"no available local Osmux CID to allocate!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (osmux_cid == -1) {
|
||||
osmux_cid = osmux_cid_pool_get_next();
|
||||
if (osmux_cid == -1) {
|
||||
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO,
|
||||
"no available Osmux CID to allocate!\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
osmux_cid_pool_get(osmux_cid);
|
||||
}
|
||||
|
||||
conn->osmux.cid = (uint8_t) osmux_cid;
|
||||
conn->osmux.cid_allocated = true;
|
||||
conn->osmux.local_cid = (uint8_t) osmux_cid;
|
||||
conn->osmux.local_cid_allocated = true;
|
||||
conn->type = MGCP_OSMUX_BSC;
|
||||
return osmux_cid;
|
||||
}
|
||||
|
@ -640,12 +632,12 @@ int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
|
|||
memset(osmuxh, 0, buf_len);
|
||||
osmuxh->ft = OSMUX_FT_DUMMY;
|
||||
osmuxh->amr_ft = AMR_FT_0;
|
||||
osmuxh->circuit_id = conn->osmux.cid;
|
||||
osmuxh->circuit_id = conn->osmux.remote_cid;
|
||||
|
||||
LOGPCONN(conn->conn, DOSMUX, LOGL_DEBUG,
|
||||
"sending OSMUX dummy load to %s:%u CID %u\n",
|
||||
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
|
||||
ntohs(conn->end.rtp_port), conn->osmux.cid);
|
||||
ntohs(conn->end.rtp_port), conn->osmux.remote_cid);
|
||||
|
||||
return mgcp_udp_send(osmux_fd.fd, &conn->end.addr,
|
||||
conn->end.rtp_port, (char*)osmuxh, buf_len);
|
||||
|
|
|
@ -301,7 +301,7 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
|
|||
|
||||
/* Attach optional OSMUX parameters */
|
||||
if (mgcp_conn_rtp_is_osmux(conn)) {
|
||||
rc = msgb_printf(sdp, MGCP_X_OSMO_OSMUX_HEADER " %u\r\n", conn->osmux.cid);
|
||||
rc = msgb_printf(sdp, MGCP_X_OSMO_OSMUX_HEADER " %u\r\n", conn->osmux.local_cid);
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ static struct msgb *handle_create_con(struct mgcp_request_data *rq)
|
|||
const char *callid = NULL;
|
||||
const char *mode = NULL;
|
||||
char *line;
|
||||
int have_sdp = 0, osmux_cid = -2;
|
||||
int have_sdp = 0, remote_osmux_cid = -2;
|
||||
struct mgcp_conn_rtp *conn = NULL;
|
||||
struct mgcp_conn *_conn = NULL;
|
||||
char conn_name[512];
|
||||
|
@ -895,7 +895,7 @@ static struct msgb *handle_create_con(struct mgcp_request_data *rq)
|
|||
/* If osmux is disabled, just skip setting it up */
|
||||
if (rq->endp->trunk->cfg->osmux_use == OSMUX_USAGE_OFF)
|
||||
break;
|
||||
osmux_cid = mgcp_osmux_setup(endp, line);
|
||||
remote_osmux_cid = mgcp_osmux_setup(endp, line);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1001,12 +1001,17 @@ mgcp_header_done:
|
|||
/* Annotate Osmux circuit ID and set it to negotiating state until this
|
||||
* is fully set up from the dummy load. */
|
||||
conn->osmux.state = OSMUX_STATE_DISABLED;
|
||||
if (osmux_cid >= -1) { /* -1 is wilcard, alloc next avail CID */
|
||||
/* If X-Osmux (remote CID) was received (-1 is wilcard), alloc next avail CID as local CID */
|
||||
if (remote_osmux_cid >= -1) {
|
||||
conn->osmux.state = OSMUX_STATE_ACTIVATING;
|
||||
if (conn_osmux_allocate_cid(conn, osmux_cid) == -1) {
|
||||
if (conn_osmux_allocate_local_cid(conn) == -1) {
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_NO_OSMUX));
|
||||
goto error2;
|
||||
}
|
||||
if (remote_osmux_cid >= 0) {
|
||||
conn->osmux.remote_cid_present = true;
|
||||
conn->osmux.remote_cid = remote_osmux_cid;
|
||||
}
|
||||
} else if (endp->trunk->cfg->osmux_use == OSMUX_USAGE_ONLY) {
|
||||
LOGPCONN(_conn, DLMGCP, LOGL_ERROR,
|
||||
"CRCX: osmux only and no osmux offered\n");
|
||||
|
@ -1118,7 +1123,7 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *rq)
|
|||
const char *mode = NULL;
|
||||
struct mgcp_conn_rtp *conn = NULL;
|
||||
const char *conn_id = NULL;
|
||||
int osmux_cid = -2;
|
||||
int remote_osmux_cid = -2;
|
||||
int rc;
|
||||
|
||||
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");
|
||||
|
@ -1176,7 +1181,7 @@ static struct msgb *handle_modify_con(struct mgcp_request_data *rq)
|
|||
/* If osmux is disabled, just skip setting it up */
|
||||
if (endp->trunk->cfg->osmux_use == OSMUX_USAGE_OFF)
|
||||
break;
|
||||
osmux_cid = mgcp_osmux_setup(endp, line);
|
||||
remote_osmux_cid = mgcp_osmux_setup(endp, line);
|
||||
break;
|
||||
}
|
||||
/* Ignore unknown X-headers */
|
||||
|
@ -1253,23 +1258,23 @@ mgcp_header_done:
|
|||
}
|
||||
|
||||
if (mgcp_conn_rtp_is_osmux(conn)) {
|
||||
OSMO_ASSERT(conn->osmux.cid_allocated);
|
||||
if (osmux_cid < -1) {
|
||||
OSMO_ASSERT(conn->osmux.local_cid_allocated);
|
||||
if (remote_osmux_cid < -1) {
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
|
||||
"MDCX: Failed to parse Osmux CID!\n");
|
||||
goto error3;
|
||||
} else if (osmux_cid == -1) {
|
||||
} else if (remote_osmux_cid == -1) {
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
|
||||
"MDCX: wilcard in MDCX is not supported!\n");
|
||||
goto error3;
|
||||
} else if (osmux_cid != (int) conn->osmux.cid) {
|
||||
} else if (conn->osmux.remote_cid_present &&
|
||||
remote_osmux_cid != (int) conn->osmux.remote_cid) {
|
||||
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
|
||||
"MDCX: changing already allocated CID is not supported!\n");
|
||||
goto error3;
|
||||
}
|
||||
/* TODO: In the future (when we have recvCID!=sendCID), we need to
|
||||
tell Osmux code that osmux_cid is to be used as sendCID for
|
||||
that conn. */
|
||||
conn->osmux.remote_cid_present = true;
|
||||
conn->osmux.remote_cid = remote_osmux_cid;
|
||||
}
|
||||
|
||||
/* MDCX may have provided a new remote address, which means we may need
|
||||
|
|
Loading…
Reference in New Issue