aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_nat.h6
-rw-r--r--openbsc/src/nat/bsc_mgcp_utils.c52
-rw-r--r--openbsc/src/nat/bsc_nat.c2
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c13
4 files changed, 65 insertions, 8 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 5f746f23..11c24dc6 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -75,6 +75,10 @@ struct bsc_connection {
struct timer_list ping_timeout;
struct timer_list pong_timeout;
+ /* mgcp related code */
+ int endpoint_status[33];
+ int last_endpoint;
+
/* a back pointer */
struct bsc_nat *nat;
};
@@ -253,7 +257,7 @@ struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat
* MGCP/Audio handling
*/
int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
-int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
+int bsc_mgcp_assign_patch(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_init(struct sccp_connections *);
void bsc_mgcp_dlcx(struct sccp_connections *);
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index 8ed93014..475e04cc 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -38,7 +38,36 @@
#include <errno.h>
#include <unistd.h>
-int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
+static int bsc_assign_endpoint(struct bsc_connection *bsc, struct sccp_connections *con)
+{
+ const int number_endpoints = ARRAY_SIZE(bsc->endpoint_status);
+ int i;
+
+ for (i = 1; i < number_endpoints; ++i) {
+ int endpoint = (bsc->last_endpoint + i) % number_endpoints;
+ if (endpoint == 0)
+ endpoint = 1;
+
+ if (bsc->endpoint_status[endpoint] == 0) {
+ bsc->endpoint_status[endpoint] = 1;
+ con->bsc_endp = endpoint;
+ bsc->last_endpoint = endpoint;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static uint16_t create_cic(int endpoint)
+{
+ int timeslot, multiplex;
+
+ mgcp_endpoint_to_timeslot(endpoint, &multiplex, &timeslot);
+ return (multiplex << 5) | (timeslot & 0x1f);
+}
+
+int bsc_mgcp_assign_patch(struct sccp_connections *con, struct msgb *msg)
{
struct sccp_connections *mcon;
struct tlv_parsed tp;
@@ -83,7 +112,17 @@ int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
}
con->msc_endp = endp;
- con->bsc_endp = endp;
+ if (bsc_assign_endpoint(con->bsc, con) != 0)
+ return -1;
+
+ /*
+ * now patch the message for the new CIC...
+ * still assumed to be one multiplex only
+ */
+ cic = htons(create_cic(con->bsc_endp));
+ memcpy((uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE),
+ &cic, sizeof(cic));
+
return 0;
}
@@ -94,6 +133,15 @@ static void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
nat->bsc_endpoints[i].transaction_id = NULL;
}
+ /* Free the endpoint status, so we can allocate it again */
+ if (nat->bsc_endpoints[i].bsc) {
+ struct bsc_connection *bsc = nat->bsc_endpoints[i].bsc;
+ if (bsc->endpoint_status[i] != 1)
+ LOGP(DNAT, LOGL_ERROR, "Endpoint %d should be allocated\n", i);
+
+ bsc->endpoint_status[i] = 0;
+ }
+
nat->bsc_endpoints[i].transaction_state = 0;
nat->bsc_endpoints[i].bsc = NULL;
}
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index 997a57f4..a380a61f 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -422,7 +422,7 @@ static int forward_sccp_to_bts(struct bsc_msc_connection *msc_con, struct msgb *
struct rate_ctr_group *ctrg;
ctrg = con->bsc->cfg->stats.ctrg;
rate_ctr_inc(&ctrg->ctr[BCFG_CTR_SCCP_CALLS]);
- if (bsc_mgcp_assign(con, msg) != 0)
+ if (bsc_mgcp_assign_patch(con, msg) != 0)
LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
} else
LOGP(DNAT, LOGL_ERROR, "Assignment command but no BSC.\n");
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index b7a89c5b..acc5de34 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -444,7 +444,7 @@ static void test_mgcp_ass_tracking(void)
msg = msgb_alloc(4096, "foo");
copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
parsed = bsc_nat_parse(msg);
- if (bsc_mgcp_assign(&con, msg) != 0) {
+ if (bsc_mgcp_assign_patch(&con, msg) != 0) {
fprintf(stderr, "Failed to handle assignment.\n");
abort();
}
@@ -454,14 +454,19 @@ static void test_mgcp_ass_tracking(void)
abort();
}
- if (con.bsc_endp != 21) {
- fprintf(stderr, "Assigned timeslot should have been 21.\n");
+ if (con.bsc_endp != 1) {
+ fprintf(stderr, "Assigned timeslot should have been 1.\n");
abort();
}
+ if (con.bsc->endpoint_status[1] != 1) {
+ fprintf(stderr, "The status on the BSC is wrong.\n");
+ abort();
+ }
+
talloc_free(parsed);
bsc_mgcp_dlcx(&con);
- if (con.bsc_endp != -1 || con.msc_endp != -1) {
+ if (con.bsc_endp != -1 || con.msc_endp != -1 || con.bsc->endpoint_status[1] != 0) {
fprintf(stderr, "Clearing should remove the mapping.\n");
abort();
}