nat: Allocate endpoints from multiple multiplexes.

This code allocates endpoints from multiple multiplexes but
will always leave 0x0 and 0x1f unassigned in the multiplex.
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 49213a5..2fc8e40 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -79,7 +79,7 @@
 
 	/* mgcp related code */
 	char *_endpoint_status;
-	int number_endpoints;
+	int number_multiplexes;
 	int last_endpoint;
 
 	/* a back pointer */
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index f002926..4df5621 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -48,7 +48,7 @@
 	if (!con->cfg)
 		return -1;
 
-	con->number_endpoints = 31 * con->cfg->number_multiplexes;
+	con->number_multiplexes = con->cfg->number_multiplexes;
 	con->_endpoint_status = talloc_zero_array(con, char,
 						  (32 * con->cfg->number_multiplexes) + 1);
 	return con->_endpoint_status == NULL;
@@ -56,13 +56,31 @@
 
 static int bsc_assign_endpoint(struct bsc_connection *bsc, struct sccp_connections *con)
 {
-	const int number_endpoints = bsc->number_endpoints;
+	int multiplex;
+	int timeslot;
+	const int number_endpoints = 32 * bsc->number_multiplexes;
 	int i;
 
-	for (i = 1; i <= number_endpoints; ++i) {
-		int endpoint = (bsc->last_endpoint + i) % number_endpoints;
-		if (endpoint == 0)
-			endpoint = 1;
+	mgcp_endpoint_to_timeslot(bsc->last_endpoint, &multiplex, &timeslot);
+	timeslot += 1;
+
+	for (i = 0; i < number_endpoints; ++i) {
+		int endpoint;
+
+		/* Wrap around timeslots */
+		if (timeslot == 0)
+			timeslot = 1;
+
+		if (timeslot == 0x1f) {
+			timeslot = 1;
+			multiplex += 1;
+		}
+
+		/* Wrap around the multiplex */
+		if (multiplex >= bsc->number_multiplexes)
+			multiplex = 0;
+
+		endpoint = mgcp_timeslot_to_endpoint(multiplex, timeslot);
 
 		if (bsc->_endpoint_status[endpoint] == 0) {
 			bsc->_endpoint_status[endpoint] = 1;
@@ -70,6 +88,8 @@
 			bsc->last_endpoint = endpoint;
 			return 0;
 		}
+
+		timeslot += 1;
 	}
 
 	return -1;
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
index 2aefe9b..5366dd3 100644
--- a/openbsc/src/nat/bsc_nat_vty.c
+++ b/openbsc/src/nat/bsc_nat_vty.c
@@ -170,10 +170,9 @@
 {
 	struct bsc_connection *con;
 	int nr = atoi(argv[0]);
-	int i;
+	int i, j, endp;
 
 	llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
-		int endpoints;
 		if (!con->cfg)
 			continue;
 		if (con->cfg->nr != nr)
@@ -184,11 +183,15 @@
 			continue;
 
 		vty_out(vty, "MGCP Status for %d%s", con->cfg->nr, VTY_NEWLINE);
-		endpoints = con->number_endpoints;
-		for (i = 1; i <= endpoints; ++i)
-			vty_out(vty, " Endpoint 0x%x %s%s", i,
-				con->_endpoint_status[i] == 0 ? "free" : "allocated",
+		for (i = 0; i < con->number_multiplexes; ++i) {
+			for (j = 0; j < 32; ++j) {
+				endp = mgcp_timeslot_to_endpoint(i, j);
+				vty_out(vty, " Endpoint 0x%x %s%s", endp,
+					con->_endpoint_status[endp] == 0 
+						? "free" : "allocated",
 				VTY_NEWLINE);
+			}
+		}
 		break;
 	}
 
@@ -632,7 +635,7 @@
 }
 
 DEFUN(cfg_bsc_nr_multip, cfg_bsc_nr_multip_cmd,
-      "number-multiplexes <1-1>",
+      "number-multiplexes <1-64>",
       "Number of multiplexes on a BSC\n" "Number of ports\n")
 {
 	struct bsc_config *conf = vty->index;
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 83d75ed..ad7ce61 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -429,6 +429,50 @@
 	talloc_free(parsed);
 }
 
+static void test_mgcp_allocations(void)
+{
+#if 0
+	struct bsc_connection *bsc;
+	struct bsc_nat *nat;
+	struct sccp_connections con;
+	int i, j;
+
+	fprintf(stderr, "Testing MGCP.\n");
+	memset(&con, 0, sizeof(con));
+
+	nat = bsc_nat_alloc();
+	nat->bsc_endpoints = talloc_zero_array(nat,
+					       struct bsc_endpoint,
+					       65);
+	nat->mgcp_cfg = mgcp_config_alloc();
+	nat->mgcp_cfg->number_endpoints = 64;
+
+	bsc = bsc_connection_alloc(nat);
+	bsc->cfg = bsc_config_alloc(nat, "foo");
+	bsc->cfg->number_multiplexes = 2;
+	bsc_config_add_lac(bsc->cfg, 2323);
+	bsc->last_endpoint = 0x22;
+	con.bsc = bsc;
+
+	bsc_init_endps_if_needed(bsc);
+
+	i  = 1;
+	do {
+		if (bsc_assign_endpoint(bsc, &con) != 0) {
+			fprintf(stderr, "failed to allocate... on iteration %d\n", i);
+			break;
+		}
+		++i;
+	} while(1);
+
+	for (i = 0; i < bsc->cfg->number_multiplexes; ++i) {
+		for (j = 0; j < 32; ++j)
+			printf("%d", bsc->_endpoint_status[i*32 + j]);
+		printf(": %d of %d\n", i*32 + 32, 32 * 8);
+	}
+#endif
+}
+
 static void test_mgcp_ass_tracking(void)
 {
 	struct bsc_connection *bsc;
@@ -964,5 +1008,6 @@
 	test_cr_filter();
 	test_dt_filter();
 	test_setup_rewrite();
+	test_mgcp_allocations();
 	return 0;
 }