aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2013-04-16 09:18:29 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2013-04-16 09:18:29 +0200
commitdc3a78f0c4b6586b9a5ffb9b79712ce3130591e6 (patch)
tree73db75000d7a85120f316967e826a80a43c62914
parent1c0c31709462af26bb1a1176c3e8b3491a26d429 (diff)
parentac04d8d55e413d49ef0a9179bccf1147e6f2a87a (diff)
Merge commit 'zecke/mgcp-statistics'
-rw-r--r--openbsc/include/openbsc/bsc_nat.h35
-rw-r--r--openbsc/include/openbsc/mgcp.h1
-rw-r--r--openbsc/src/libmgcp/mgcp_protocol.c30
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c291
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c11
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_utils.c1
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_vty.c22
-rw-r--r--openbsc/tests/bsc-nat/Makefile.am1
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c7
-rw-r--r--openbsc/tests/mgcp/mgcp_test.c25
-rw-r--r--openbsc/tests/mgcp/mgcp_test.ok3
11 files changed, 392 insertions, 35 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 1698fa47f..6860342a0 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -32,6 +32,7 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/statistics.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/sccp/sccp_types.h>
#include <regex.h>
@@ -111,6 +112,9 @@ struct bsc_connection {
int number_multiplexes;
int max_endpoints;
int last_endpoint;
+ int next_transaction;
+ uint32_t pending_dlcx_count;
+ struct llist_head pending_dlcx;
/* track the pending commands for this BSC */
struct llist_head cmd_pending;
@@ -270,6 +274,7 @@ struct bsc_nat {
struct mgcp_config *mgcp_cfg;
uint8_t mgcp_msg[4096];
int mgcp_length;
+ int mgcp_ipa;
/* msc things */
struct llist_head dests;
@@ -331,6 +336,33 @@ struct bsc_nat_ussd_con {
struct osmo_timer_list auth_timeout;
};
+struct bsc_nat_call_stats {
+ struct llist_head entry;
+
+ struct sccp_source_reference remote_ref;
+ struct sccp_source_reference src_ref; /* as seen by the MSC */
+
+ /* mgcp options */
+ uint32_t ci;
+ int bts_rtp_port;
+ int net_rtp_port;
+ struct in_addr bts_addr;
+ struct in_addr net_addr;
+
+
+ /* as witnessed by the NAT */
+ uint32_t net_ps;
+ uint32_t net_os;
+ uint32_t bts_pr;
+ uint32_t bts_or;
+ uint32_t bts_expected;
+ uint32_t bts_jitter;
+ int bts_loss;
+
+ uint32_t trans_id;
+ int msc_endpoint;
+};
+
struct bsc_nat_reject_cause {
int lu_reject_cause;
int cm_reject_cause;
@@ -463,6 +495,9 @@ struct bsc_nat_barr_entry {
int bsc_nat_barr_adapt(void *ctx, struct rb_root *rbtree, const struct osmo_config_list *);
int bsc_nat_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu);
+void bsc_nat_send_mgcp_to_msc(struct bsc_nat *bsc_nat, struct msgb *msg);
+void bsc_nat_handle_mgcp(struct bsc_nat *bsc, struct msgb *msg);
+
struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat, int port);
void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending);
int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg);
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 7a416ddd1..811dcfda7 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -172,6 +172,7 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
void mgcp_free_endp(struct mgcp_endpoint *endp);
int mgcp_reset_transcoder(struct mgcp_config *cfg);
void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
+int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
/*
* format helper functions
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 6919a591d..dc5e0f992 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -1167,9 +1167,37 @@ void mgcp_format_stats(struct mgcp_endpoint *endp, char *msg, size_t size)
&expected, &ploss);
jitter = mgcp_state_calc_jitter(&endp->net_state);
- snprintf(msg, size, "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%d",
+ snprintf(msg, size, "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
endp->bts_end.packets, endp->bts_end.octets,
endp->net_end.packets, endp->net_end.octets,
ploss, jitter);
msg[size - 1] = '\0';
}
+
+int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os,
+ uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter)
+{
+ char *line, *save;
+ int rc;
+
+ /* initialize with bad values */
+ *ps = *os = *pr = *_or = *jitter = UINT_MAX;
+ *loss = INT_MAX;
+
+
+ line = strtok_r((char *) msg->l2h, "\r\n", &save);
+ if (!line)
+ return -1;
+
+ /* this can only parse the message that is created above... */
+ for_each_line(line, save) {
+ switch (line[0]) {
+ case 'P':
+ rc = sscanf(line, "P: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
+ ps, os, pr, _or, loss, jitter);
+ return rc == 6 ? 0 : -1;
+ }
+ }
+
+ return -1;
+}
diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
index e5384d1a7..85f940b49 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c
@@ -49,6 +49,7 @@
#include <openbsc/ipaccess.h>
#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>
+#include <openbsc/control_cmd.h>
#include <osmocom/sccp/sccp.h>
@@ -62,6 +63,22 @@
#include <errno.h>
#include <unistd.h>
+static void send_direct(struct bsc_nat *nat, struct msgb *output)
+{
+ if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, output) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
+ msgb_free(output);
+ }
+}
+
+static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output)
+{
+ if (nat->mgcp_ipa)
+ bsc_nat_send_mgcp_to_msc(nat, output);
+ else
+ send_direct(nat, output);
+}
+
int bsc_mgcp_nr_multiplexes(int max_endpoints)
{
int div = max_endpoints / 32;
@@ -257,17 +274,23 @@ static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, int port, struct mgcp
return;
}
- #warning "The MDCX is not send to the BSC. It should"
+ bsc_write_mgcp(bsc, (uint8_t *) buf, len);
}
-static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint)
+static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint, int trans)
{
char buf[2096];
int len;
+ /*
+ * The following is a bit of a spec violation. According to the
+ * MGCP grammar the transaction id is are upto 9 digits but we
+ * prefix it with an alpha numeric value so we can easily recognize
+ * it as a response.
+ */
len = snprintf(buf, sizeof(buf),
- "DLCX 26 %x@mgw MGCP 1.0\r\n"
- "Z: noanswer\r\n", endpoint);
+ "DLCX nat-%u %x@mgw MGCP 1.0\r\n",
+ trans, endpoint);
if (len < 0) {
LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
return;
@@ -282,18 +305,173 @@ void bsc_mgcp_init(struct sccp_connections *con)
con->bsc_endp = -1;
}
+/**
+ * This code will remember the network side of the audio statistics and
+ * once the internal DLCX response arrives this can be combined with the
+ * the BSC side and forwarded as a trap.
+ */
+static void remember_pending_dlcx(struct sccp_connections *con, uint32_t transaction)
+{
+ struct bsc_nat_call_stats *stats;
+ struct bsc_connection *bsc = con->bsc;
+ struct mgcp_endpoint *endp;
+
+ stats = talloc_zero(bsc, struct bsc_nat_call_stats);
+ if (!stats) {
+ LOGP(DNAT, LOGL_NOTICE,
+ "Failed to allocate statistics for endpoint 0x%x\n",
+ con->msc_endp);
+ return;
+ }
+
+ /* take the endpoint here */
+ endp = &bsc->nat->mgcp_cfg->trunk.endpoints[con->msc_endp];
+
+ stats->remote_ref = con->remote_ref;
+ stats->src_ref = con->patched_ref;
+
+ stats->ci = endp->ci;
+ stats->bts_rtp_port = endp->bts_end.rtp_port;
+ stats->bts_addr = endp->bts_end.addr;
+ stats->net_rtp_port = endp->net_end.rtp_port;
+ stats->net_addr = endp->net_end.addr;
+
+ stats->net_ps = endp->net_end.packets;
+ stats->net_os = endp->net_end.octets;
+ stats->bts_pr = endp->bts_end.packets;
+ stats->bts_or = endp->bts_end.octets;
+ mgcp_state_calc_loss(&endp->bts_state, &endp->bts_end,
+ &stats->bts_expected, &stats->bts_loss);
+ stats->bts_jitter = mgcp_state_calc_jitter(&endp->bts_state);
+
+ stats->trans_id = transaction;
+ stats->msc_endpoint = con->msc_endp;
+
+ /*
+ * Too many pending requests.. let's remove the first two items.
+ */
+ if (!llist_empty(&bsc->pending_dlcx) &&
+ bsc->pending_dlcx_count >= bsc->cfg->max_endpoints * 3) {
+ struct bsc_nat_call_stats *tmp;
+ LOGP(DNAT, LOGL_ERROR,
+ "Too many(%d) pending DLCX responses on BSC: %d\n",
+ bsc->pending_dlcx_count, bsc->cfg->nr);
+ bsc->pending_dlcx_count -= 1;
+ tmp = (struct bsc_nat_call_stats *) bsc->pending_dlcx.next;
+ llist_del(&tmp->entry);
+ talloc_free(tmp);
+ }
+
+ bsc->pending_dlcx_count += 1;
+ llist_add_tail(&stats->entry, &bsc->pending_dlcx);
+}
+
void bsc_mgcp_dlcx(struct sccp_connections *con)
{
/* send a DLCX down the stream */
if (con->bsc_endp != -1 && con->bsc->_endpoint_status) {
+ LOGP(DNAT, LOGL_NOTICE,
+ "Endpoint 0x%x was allocated for bsc: %d. Freeing it.\n",
+ con->bsc_endp, con->bsc->cfg->nr);
if (con->bsc->_endpoint_status[con->bsc_endp] != 1)
LOGP(DNAT, LOGL_ERROR, "Endpoint 0x%x was not in use\n", con->bsc_endp);
+ remember_pending_dlcx(con, con->bsc->next_transaction);
con->bsc->_endpoint_status[con->bsc_endp] = 0;
- bsc_mgcp_send_dlcx(con->bsc, con->bsc_endp);
+ bsc_mgcp_send_dlcx(con->bsc, con->bsc_endp, con->bsc->next_transaction++);
bsc_mgcp_free_endpoint(con->bsc->nat, con->msc_endp);
}
bsc_mgcp_init(con);
+
+}
+
+/*
+ * Search for the pending request
+ */
+static void handle_dlcx_response(struct bsc_connection *bsc, struct msgb *msg,
+ int code, const char *transaction)
+{
+ uint32_t trans_id = UINT32_MAX;
+ uint32_t b_ps, b_os, n_pr, n_or, jitter;
+ int loss;
+ struct bsc_nat_call_stats *tmp, *stat = NULL;
+ struct ctrl_cmd *cmd;
+
+ /* parse the transaction identifier */
+ int rc = sscanf(transaction, "nat-%u", &trans_id);
+ if (rc != 1) {
+ LOGP(DNAT, LOGL_ERROR, "Can not parse transaction id: '%s'\n",
+ transaction);
+ return;
+ }
+
+ /* find the answer for the request we made */
+ llist_for_each_entry(tmp, &bsc->pending_dlcx, entry) {
+ if (trans_id != tmp->trans_id)
+ continue;
+
+ stat = tmp;
+ break;
+ }
+
+ if (!stat) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Can not find transaction for: %u\n", trans_id);
+ return;
+ }
+
+ /* attempt to parse the data now */
+ rc = mgcp_parse_stats(msg, &b_ps, &b_os, &n_pr, &n_or, &loss, &jitter);
+ if (rc != 0)
+ LOGP(DNAT, LOGL_ERROR,
+ "Can not parse connection statistics: %d\n", rc);
+
+ /* send a trap now */
+ cmd = ctrl_cmd_create(bsc, CTRL_TYPE_TRAP);
+ if (!cmd) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Creating a ctrl cmd failed.\n");
+ goto free_stat;
+ }
+
+ cmd->id = "0";
+ cmd->variable = talloc_asprintf(cmd, "net.0.bsc.%d.call_stats.v2",
+ bsc->cfg->nr);
+ cmd->reply = talloc_asprintf(cmd,
+ "mg_ip_addr=%s,mg_port=%d,",
+ inet_ntoa(stat->net_addr),
+ stat->net_rtp_port);
+ cmd->reply = talloc_asprintf_append(cmd->reply,
+ "endpoint_ip_addr=%s,endpoint_port=%d,",
+ inet_ntoa(stat->bts_addr),
+ stat->bts_rtp_port);
+ cmd->reply = talloc_asprintf_append(cmd->reply,
+ "nat_pkt_in=%u,nat_pkt_out=%u,"
+ "nat_bytes_in=%u,nat_bytes_out=%u,"
+ "nat_jitter=%u,nat_pkt_lost=%d,",
+ stat->bts_pr, stat->net_ps,
+ stat->bts_or, stat->net_os,
+ stat->bts_jitter, stat->bts_loss);
+ cmd->reply = talloc_asprintf_append(cmd->reply,
+ "bsc_pkt_in=%u,bsc_pkt_out=%u,"
+ "bsc_bytes_in=%u,bsc_bytes_out=%u,"
+ "bsc_jitter=%u,bsc_pkt_lost=%d,",
+ n_pr, b_ps,
+ n_or, b_os,
+ jitter, loss);
+ cmd->reply = talloc_asprintf_append(cmd->reply,
+ "sccp_src_ref=%u,sccp_dst_ref=%u",
+ sccp_src_ref_to_int(&stat->src_ref),
+ sccp_src_ref_to_int(&stat->remote_ref));
+
+ /* send it and be done */
+ ctrl_cmd_send_to_all(bsc->nat->ctrl, cmd);
+ talloc_free(cmd);
+
+free_stat:
+ bsc->pending_dlcx_count -= 1;
+ llist_del(&stat->entry);
+ talloc_free(stat);
}
@@ -314,7 +492,8 @@ struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
if (con)
return con;
- LOGP(DMGCP, LOGL_ERROR, "Failed to find the connection.\n");
+ LOGP(DMGCP, LOGL_ERROR,
+ "Failed to find the connection for endpoint: 0x%x\n", endpoint);
return NULL;
}
@@ -419,7 +598,7 @@ static void free_chan_downstream(struct mgcp_endpoint *endp, struct bsc_endpoint
ENDPOINT_NUMBER(endp));
} else {
if (con->bsc == bsc) {
- bsc_mgcp_send_dlcx(bsc, con->bsc_endp);
+ bsc_mgcp_send_dlcx(bsc, con->bsc_endp, con->bsc->next_transaction++);
} else {
LOGP(DMGCP, LOGL_ERROR,
"Endpoint belongs to a different BSC\n");
@@ -436,6 +615,9 @@ static void free_chan_downstream(struct mgcp_endpoint *endp, struct bsc_endpoint
* this transaction and if it belongs to the BSC. Then we will
* need to patch the content to point to the local network and we
* need to update the I: that was assigned by the BSS.
+ *
+ * Only responses to CRCX and DLCX should arrive here. The DLCX
+ * needs to be handled specially to combine the two statistics.
*/
void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
{
@@ -472,6 +654,11 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
break;
}
+ if (!bsc_endp && strncmp("nat-", transaction_id, 4) == 0) {
+ handle_dlcx_response(bsc, msg, code, transaction_id);
+ return;
+ }
+
if (!bsc_endp) {
LOGP(DMGCP, LOGL_ERROR, "Could not find active endpoint: %s for msg: '%s'\n",
transaction_id, (const char *) msg->l2h);
@@ -502,16 +689,16 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
return;
}
- if (osmo_wqueue_enqueue(&bsc->nat->mgcp_cfg->gw_fd, output) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
- msgb_free(output);
- }
+ mgcp_queue_for_call_agent(bsc->nat, output);
}
int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60])
{
+ int rc;
/* we want to parse two strings */
- return sscanf(str, "%3d %59s\n", code, transaction) != 2;
+ rc = sscanf(str, "%3d %59s\n", code, transaction) != 2;
+ transaction[59] = '\0';
+ return rc;
}
uint32_t bsc_mgcp_extract_ci(const char *str)
@@ -651,6 +838,38 @@ copy:
return output;
}
+/*
+ * This comes from the MSC and we will now parse it. The caller needs
+ * to free the msgb.
+ */
+void bsc_nat_handle_mgcp(struct bsc_nat *nat, struct msgb *msg)
+{
+ struct msgb *resp;
+
+ if (!nat->mgcp_ipa) {
+ LOGP(DMGCP, LOGL_ERROR, "MGCP message not allowed on IPA.\n");
+ return;
+ }
+
+ if (msgb_l2len(msg) > sizeof(nat->mgcp_msg) - 1) {
+ LOGP(DMGCP, LOGL_ERROR, "MGCP msg too big for handling.\n");
+ return;
+ }
+
+ memcpy(nat->mgcp_msg, msg->l2h, msgb_l2len(msg));
+ nat->mgcp_length = msgb_l2len(msg);
+ nat->mgcp_msg[nat->mgcp_length] = '\0';
+
+ /* now handle the message */
+ resp = mgcp_handle_message(nat->mgcp_cfg, msg);
+
+ /* we do have a direct answer... e.g. AUEP */
+ if (resp)
+ mgcp_queue_for_call_agent(nat, resp);
+
+ return;
+}
+
static int mgcp_do_read(struct osmo_fd *fd)
{
struct bsc_nat *nat;
@@ -680,12 +899,8 @@ static int mgcp_do_read(struct osmo_fd *fd)
msgb_free(msg);
/* we do have a direct answer... e.g. AUEP */
- if (resp) {
- if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, resp) != 0) {
- LOGP(DMGCP, LOGL_ERROR, "Failed to enqueue msg.\n");
- msgb_free(resp);
- }
- }
+ if (resp)
+ mgcp_queue_for_call_agent(nat, resp);
return 0;
}
@@ -704,21 +919,10 @@ static int mgcp_do_write(struct osmo_fd *bfd, struct msgb *msg)
return rc;
}
-int bsc_mgcp_nat_init(struct bsc_nat *nat)
+static int init_mgcp_socket(struct bsc_nat *nat, struct mgcp_config *cfg)
{
- int on;
struct sockaddr_in addr;
- struct mgcp_config *cfg = nat->mgcp_cfg;
-
- if (!cfg->call_agent_addr) {
- LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
- return -1;
- }
-
- if (cfg->bts_ip) {
- LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
- return -1;
- }
+ int on;
cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
if (cfg->gw_fd.bfd.fd < 0) {
@@ -764,6 +968,31 @@ int bsc_mgcp_nat_init(struct bsc_nat *nat)
return -1;
}
+ return 0;
+}
+
+int bsc_mgcp_nat_init(struct bsc_nat *nat)
+{
+ struct mgcp_config *cfg = nat->mgcp_cfg;
+
+ if (!cfg->call_agent_addr) {
+ LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
+ return -1;
+ }
+
+ if (cfg->bts_ip) {
+ LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
+ return -1;
+ }
+
+ /* initialize the MGCP socket */
+ if (!nat->mgcp_ipa) {
+ int rc = init_mgcp_socket(nat, cfg);
+ if (rc != 0)
+ return rc;
+ }
+
+
/* some more MGCP config handling */
cfg->data = nat;
cfg->policy_cb = bsc_mgcp_policy_cb;
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 792d33c23..e70f54952 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -333,6 +333,12 @@ static void send_mgcp_reset(struct bsc_connection *bsc)
bsc_write_mgcp(bsc, mgcp_reset, sizeof mgcp_reset - 1);
}
+void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg)
+{
+ ipaccess_prepend_header(msg, IPAC_PROTO_MGCP_OLD);
+ queue_for_msc(nat->msc_con, msg);
+}
+
/*
* Below is the handling of messages coming
* from the MSC and need to be forwarded to
@@ -820,8 +826,11 @@ static int ipaccess_msc_read_cb(struct osmo_fd *bfd)
initialize_msc_if_needed(msc_con);
else if (msg->l2h[0] == IPAC_MSGT_ID_GET)
send_id_get_response(msc_con);
- } else if (hh->proto == IPAC_PROTO_SCCP)
+ } else if (hh->proto == IPAC_PROTO_SCCP) {
forward_sccp_to_bts(msc_con, msg);
+ } else if (hh->proto == IPAC_PROTO_MGCP_OLD) {
+ bsc_nat_handle_mgcp(nat, msg);
+ }
msgb_free(msg);
return 0;
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
index 0c56a8cd9..2e6d9a363 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
@@ -132,6 +132,7 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
con->nat = nat;
osmo_wqueue_init(&con->write_queue, 100);
INIT_LLIST_HEAD(&con->cmd_pending);
+ INIT_LLIST_HEAD(&con->pending_dlcx);
return con;
}
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index 7bbc89059..e5993b4a8 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -143,6 +143,8 @@ static int config_write_nat(struct vty *vty)
write_acc_lst(vty, lst);
llist_for_each_entry(pgroup, &_nat->paging_groups, entry)
write_pgroup_lst(vty, pgroup);
+ if (_nat->mgcp_ipa)
+ vty_out(vty, " mgcp-through-msc-ipa%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -204,10 +206,11 @@ DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
- vty_out(vty, "BSC nr: %d auth: %d fd: %d peername: %s%s",
+ vty_out(vty, "BSC nr: %d auth: %d fd: %d peername: %s pending-stats: %u%s",
con->cfg ? con->cfg->nr : -1,
con->authenticated, con->write_queue.bfd.fd,
- inet_ntoa(sock.sin_addr), VTY_NEWLINE);
+ inet_ntoa(sock.sin_addr), con->pending_dlcx_count,
+ VTY_NEWLINE);
}
return CMD_SUCCESS;
@@ -657,6 +660,20 @@ DEFUN(cfg_nat_ussd_local,
return CMD_SUCCESS;
}
+DEFUN(cfg_nat_mgcp_ipa,
+ cfg_nat_mgcp_ipa_cmd,
+ "mgcp-through-msc-ipa",
+ "This needs to be set at start. Handle MGCP messages through "
+ "the IPA protocol and not through the UDP socket.\n")
+{
+ if (_nat->mgcp_cfg->data)
+ vty_out(vty,
+ "%%the setting will not be applied right now.%s",
+ VTY_NEWLINE);
+ _nat->mgcp_ipa = 1;
+ return CMD_SUCCESS;
+}
+
/* per BSC configuration */
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR",
"BSC configuration\n" "Identifier of the BSC\n")
@@ -1086,6 +1103,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(NAT_NODE, &cfg_nat_ussd_query_cmd);
install_element(NAT_NODE, &cfg_nat_ussd_token_cmd);
install_element(NAT_NODE, &cfg_nat_ussd_local_cmd);
+ install_element(NAT_NODE, &cfg_nat_mgcp_ipa_cmd);
/* access-list */
install_element(NAT_NODE, &cfg_lst_imsi_allow_cmd);
diff --git a/openbsc/tests/bsc-nat/Makefile.am b/openbsc/tests/bsc-nat/Makefile.am
index e284851a1..9b71d095c 100644
--- a/openbsc/tests/bsc-nat/Makefile.am
+++ b/openbsc/tests/bsc-nat/Makefile.am
@@ -14,6 +14,7 @@ bsc_nat_test_SOURCES = bsc_nat_test.c \
$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite.c \
$(top_srcdir)/src/osmo-bsc_nat/bsc_mgcp_utils.c
bsc_nat_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
+ $(top_srcdir)/src/libctrl/libctrl.a \
$(top_srcdir)/src/libmgcp/libmgcp.a \
$(top_srcdir)/src/libtrau/libtrau.a \
$(top_srcdir)/src/libcommon/libcommon.a \
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 66b4ff5a7..c2931f98b 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -514,6 +514,7 @@ static void test_mgcp_ass_tracking(void)
33);
nat->mgcp_cfg = mgcp_config_alloc();
nat->mgcp_cfg->trunk.number_endpoints = 64;
+ mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk);
bsc = bsc_connection_alloc(nat);
bsc->cfg = bsc_config_alloc(nat, "foo");
@@ -1242,3 +1243,9 @@ int main(int argc, char **argv)
printf("Testing execution completed.\n");
return 0;
}
+
+/* stub */
+void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg)
+{
+ abort();
+}
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index 4dfd2abe3..5565e7316 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -323,6 +323,30 @@ static void test_packet_loss_calc(void)
}
}
+static void test_mgcp_stats(void)
+{
+ printf("Testing stat parsing\n");
+
+ uint32_t bps, bos, pr, _or, jitter;
+ struct msgb *msg;
+ int loss;
+ int rc;
+
+ msg = create_msg(DLCX_RET);
+ rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
+ printf("Parsing result: %d\n", rc);
+ if (bps != 0 || bos != 0 || pr != 0 || _or != 0 || loss != 0 || jitter != 0)
+ printf("FAIL: Parsing failed1.\n");
+ msgb_free(msg);
+
+ msg = create_msg("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n");
+ rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
+ printf("Parsing result: %d\n", rc);
+ if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3 || jitter != 40)
+ printf("FAIL: Parsing failed2.\n");
+ msgb_free(msg);
+}
+
int main(int argc, char **argv)
{
osmo_init_logging(&log_info);
@@ -331,6 +355,7 @@ int main(int argc, char **argv)
test_retransmission();
test_packet_loss_calc();
test_rqnt_cb();
+ test_mgcp_stats();
printf("Done\n");
return EXIT_SUCCESS;
diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok
index 224bba8d7..8711e38f2 100644
--- a/openbsc/tests/mgcp/mgcp_test.ok
+++ b/openbsc/tests/mgcp/mgcp_test.ok
@@ -25,4 +25,7 @@ Re-transmitting MDCX3
Testing DLCX
Re-transmitting DLCX
Testing packet loss calculation.
+Testing stat parsing
+Parsing result: 0
+Parsing result: 0
Done