aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2017-06-08 14:18:47 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-06-18 01:49:29 +0200
commite228956dd3d2d59c0cd742289fa91678c989ea5d (patch)
tree255fdf9a2bad4291cfbb5b9263f8bec0108b1f25
parent2395f55300b3f76b090d3c870c998f6663ad6281 (diff)
mgcp: improve endpoint management
Currently the assignment of endpoint identifiers works by just incrementing a counter. The mgcpgw only has a limited amount of endpoint identifiers avaliable, this means we will run out of endpoints after only a few calls. This commit adds a mechanism to keep track of used endpoint identifiers so unused endpoint identifiers can be re-used
-rw-r--r--openbsc/include/openbsc/mgcpgw_client.h10
-rw-r--r--openbsc/src/libmgcp/mgcpgw_client.c72
-rw-r--r--openbsc/src/libmgcp/mgcpgw_client_vty.c30
3 files changed, 104 insertions, 8 deletions
diff --git a/openbsc/include/openbsc/mgcpgw_client.h b/openbsc/include/openbsc/mgcpgw_client.h
index 8220cfa51..87fb27627 100644
--- a/openbsc/include/openbsc/mgcpgw_client.h
+++ b/openbsc/include/openbsc/mgcpgw_client.h
@@ -24,8 +24,8 @@ struct mgcpgw_client_conf {
int local_port;
const char *remote_addr;
int remote_port;
- unsigned int first_endpoint;
- unsigned int last_endpoint;
+ uint16_t first_endpoint;
+ uint16_t last_endpoint;
};
struct mgcp_response_head {
@@ -63,7 +63,11 @@ const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp);
uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp);
uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp);
-unsigned int mgcpgw_client_next_endpoint(struct mgcpgw_client *client);
+/* Find and seize an unsused endpoint id */
+int mgcpgw_client_next_endpoint(struct mgcpgw_client *client);
+
+/* Release a seized endpoint id to make it available again for other calls */
+void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client);
int mgcp_response_parse_params(struct mgcp_response *r);
diff --git a/openbsc/src/libmgcp/mgcpgw_client.c b/openbsc/src/libmgcp/mgcpgw_client.c
index 0c2106704..2cafcf2a0 100644
--- a/openbsc/src/libmgcp/mgcpgw_client.c
+++ b/openbsc/src/libmgcp/mgcpgw_client.c
@@ -40,8 +40,13 @@ struct mgcpgw_client {
uint32_t remote_addr;
struct osmo_wqueue wq;
mgcp_trans_id_t next_trans_id;
- uint16_t next_endpoint;
struct llist_head responses_pending;
+ struct llist_head inuse_endpoints;
+};
+
+struct mgcp_inuse_endpoint {
+ struct llist_head entry;
+ uint16_t id;
};
void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf)
@@ -52,13 +57,67 @@ void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf)
.local_port = -1,
.remote_addr = NULL,
.remote_port = -1,
+ .first_endpoint = 0,
+ .last_endpoint = 0,
};
}
-unsigned int mgcpgw_client_next_endpoint(struct mgcpgw_client *client)
+/* Test if a given endpoint id is currently in use */
+static bool endpoint_in_use(uint16_t id, struct mgcpgw_client *client)
{
- /* FIXME: wrapping / cleanup + re-use */
- return client->next_endpoint ++;
+ struct mgcp_inuse_endpoint *endpoint;
+ llist_for_each_entry(endpoint, &client->inuse_endpoints, entry) {
+ if (endpoint->id == id)
+ return true;
+ }
+
+ return false;
+}
+
+/* Find and seize an unsused endpoint id */
+int mgcpgw_client_next_endpoint(struct mgcpgw_client *client)
+{
+ int i;
+ uint16_t first_endpoint = client->actual.first_endpoint;
+ uint16_t last_endpoint = client->actual.last_endpoint;
+ struct mgcp_inuse_endpoint *endpoint;
+
+ /* Use the maximum permitted range if the VTY
+ * configuration does not specify a range */
+ if (client->actual.last_endpoint == 0) {
+ first_endpoint = 1;
+ last_endpoint = 65534;
+ }
+
+ /* Test the permitted endpoint range for an endpoint
+ * number that is not in use. When a suitable endpoint
+ * number can be found, seize it by adding it to the
+ * inuse list. */
+ for (i=first_endpoint;i<last_endpoint;i++)
+ {
+ if (endpoint_in_use(i,client) == false) {
+ endpoint = talloc_zero(client, struct mgcp_inuse_endpoint);
+ endpoint->id = i;
+ llist_add_tail(&endpoint->entry, &client->inuse_endpoints);
+ return endpoint->id;
+ }
+ }
+
+ /* All endpoints are busy! */
+ return -EINVAL;
+}
+
+/* Release a seized endpoint id to make it available again for other calls */
+void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client)
+{
+ struct mgcp_inuse_endpoint *endpoint;
+ struct mgcp_inuse_endpoint *endpoint_tmp;
+ llist_for_each_entry_safe(endpoint, endpoint_tmp, &client->inuse_endpoints, entry) {
+ if (endpoint->id == id) {
+ llist_del(&endpoint->entry);
+ talloc_free(endpoint);
+ }
+ }
}
static void mgcpgw_client_handle_response(struct mgcpgw_client *mgcp,
@@ -281,9 +340,9 @@ struct mgcpgw_client *mgcpgw_client_init(void *ctx,
mgcp = talloc_zero(ctx, struct mgcpgw_client);
INIT_LLIST_HEAD(&mgcp->responses_pending);
+ INIT_LLIST_HEAD(&mgcp->inuse_endpoints);
mgcp->next_trans_id = 1;
- mgcp->next_endpoint = 1;
mgcp->actual.local_addr = conf->local_addr ? conf->local_addr :
MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT;
@@ -295,6 +354,9 @@ struct mgcpgw_client *mgcpgw_client_init(void *ctx,
mgcp->actual.remote_port = conf->remote_port >= 0 ? (uint16_t)conf->remote_port :
MGCPGW_CLIENT_REMOTE_PORT_DEFAULT;
+ mgcp->actual.first_endpoint = conf->first_endpoint > 0 ? (uint16_t)conf->first_endpoint : 0;
+ mgcp->actual.last_endpoint = conf->last_endpoint > 0 ? (uint16_t)conf->last_endpoint : 0;
+
return mgcp;
}
diff --git a/openbsc/src/libmgcp/mgcpgw_client_vty.c b/openbsc/src/libmgcp/mgcpgw_client_vty.c
index a42ee4e5d..8670192e9 100644
--- a/openbsc/src/libmgcp/mgcpgw_client_vty.c
+++ b/openbsc/src/libmgcp/mgcpgw_client_vty.c
@@ -79,10 +79,32 @@ DEFUN(cfg_mgcpgw_remote_port, cfg_mgcpgw_remote_port_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_mgcpgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
+ "mgcpgw endpoint-range <1-65534> <1-65534>",
+ MGCPGW_STR "usable range of endpoint identifiers\n"
+ "set first useable endpoint identifier\n"
+ "set the last useable endpoint identifier\n")
+{
+ uint16_t first_endpoint = atoi(argv[0]);
+ uint16_t last_endpoint = atoi(argv[1]);
+
+ if (last_endpoint < first_endpoint) {
+ vty_out(vty, "last endpoint must be greater than first endpoint!%s",
+ VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ global_mgcpgw_client_conf->first_endpoint = first_endpoint;
+ global_mgcpgw_client_conf->last_endpoint = last_endpoint;
+ return CMD_SUCCESS;
+}
+
int mgcpgw_client_config_write(struct vty *vty, const char *indent)
{
const char *addr;
int port;
+ uint16_t first_endpoint;
+ uint16_t last_endpoint;
addr = global_mgcpgw_client_conf->local_addr;
if (addr)
@@ -102,6 +124,13 @@ int mgcpgw_client_config_write(struct vty *vty, const char *indent)
vty_out(vty, "%smgcpgw remote-port %u%s", indent,
(uint16_t)port, VTY_NEWLINE);
+ first_endpoint = global_mgcpgw_client_conf->first_endpoint;
+ last_endpoint = global_mgcpgw_client_conf->last_endpoint;
+ if (last_endpoint != 0) {
+ vty_out(vty, "%smgcpgw endpoint-range %u %u%s", indent,
+ first_endpoint, last_endpoint, VTY_NEWLINE);
+ }
+
return CMD_SUCCESS;
}
@@ -113,4 +142,5 @@ void mgcpgw_client_vty_init(int node, struct mgcpgw_client_conf *conf)
install_element(node, &cfg_mgcpgw_local_port_cmd);
install_element(node, &cfg_mgcpgw_remote_ip_cmd);
install_element(node, &cfg_mgcpgw_remote_port_cmd);
+ install_element(node, &cfg_mgcpgw_endpoint_range_cmd);
}