nat: Attempt to assign the BSC Timeslot based on a free list

Do attempt to not reassign an endpoint immediately but go
to the next free one.
This commit is contained in:
Holger Hans Peter Freyther 2010-08-28 18:22:14 +08:00
parent 39cd32e650
commit 45fd07dc33
4 changed files with 65 additions and 8 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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");

View File

@ -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();
}