Change in osmo-mgw[master]: mgcp_client: allow to reset endpoints on startup

laforge gerrit-no-reply at lists.osmocom.org
Tue Aug 17 12:12:24 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-mgw/+/25008 )

Change subject: mgcp_client: allow to reset endpoints on startup
......................................................................

mgcp_client: allow to reset endpoints on startup

Depending on the usecase of osmo_mpcg_client it may be helpful to send a
DLCX to certain endpoints. Usually this would be a wildcarded endpoint
that resets the entire trunk to drop lingering RTP flows which may still
present after a restart/crash, but it might be also a group of specific
endpoints. The user may specify an arbitrary amount of endpoints where
the mgcp client will send a DLCX to. It does not matter if the endpoints
are wildcarded or not.

Change-Id: I47e7ff858d5067b46d52329be5f362ff61c0dff8
Related: SYS#5535
---
M TODO-RELEASE
M include/osmocom/mgcp_client/mgcp_client.h
M include/osmocom/mgcp_client/mgcp_client_internal.h
M src/libosmo-mgcp-client/mgcp_client.c
M src/libosmo-mgcp-client/mgcp_client_vty.c
5 files changed, 135 insertions(+), 20 deletions(-)

Approvals:
  Jenkins Builder: Verified
  osmith: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/TODO-RELEASE b/TODO-RELEASE
index add44f1..3b31cde 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -25,3 +25,4 @@
 #
 #library		what		description / commit summary line
 update dependency to libosmocore > 1.5.1 for our use of osmo_sock_set_dscp()
+libosmo-mgcp-client  struct mgcp_client_conf ABI breackage
\ No newline at end of file
diff --git a/include/osmocom/mgcp_client/mgcp_client.h b/include/osmocom/mgcp_client/mgcp_client.h
index 02996a7..e9fe0ae 100644
--- a/include/osmocom/mgcp_client/mgcp_client.h
+++ b/include/osmocom/mgcp_client/mgcp_client.h
@@ -26,6 +26,12 @@
 	/* By default, we are always addressing the MGW with e.g. 'rtpbridge/123 at mgw'.
 	 * If this is nonempty, the contained name will be used instead of 'mgw'. */
 	char endpoint_domain_name[MGCP_ENDPOINT_MAXLEN];
+
+	/* The user may configure certain endpoint names that are reset via DLCX
+	 * on startup. Usually this will be one wildcarded endpoint e.g.
+	 * 'rtpbridge/(wildcard)' or a number of specific E1 like e.g.
+	 * 'ds/e1-0/s-3/su16-4' */
+	struct llist_head reset_epnames;
 };
 
 typedef unsigned int mgcp_trans_id_t;
diff --git a/include/osmocom/mgcp_client/mgcp_client_internal.h b/include/osmocom/mgcp_client/mgcp_client_internal.h
index b4b3b02..44b9022 100644
--- a/include/osmocom/mgcp_client/mgcp_client_internal.h
+++ b/include/osmocom/mgcp_client/mgcp_client_internal.h
@@ -4,6 +4,12 @@
 
 #define MSGB_CB_MGCP_TRANS_ID 0
 
+/* Struct that holds one endpoint name */
+struct reset_ep {
+	struct llist_head list;
+	char name[MGCP_ENDPOINT_MAXLEN];
+};
+
 struct mgcp_client {
 	struct mgcp_client_conf actual;
 	struct osmo_wqueue wq;
diff --git a/src/libosmo-mgcp-client/mgcp_client.c b/src/libosmo-mgcp-client/mgcp_client.c
index 69d687b..440cd96 100644
--- a/src/libosmo-mgcp-client/mgcp_client.c
+++ b/src/libosmo-mgcp-client/mgcp_client.c
@@ -200,6 +200,8 @@
 		.remote_addr = NULL,
 		.remote_port = -1,
 	};
+
+	INIT_LLIST_HEAD(&conf->reset_epnames);
 }
 
 static void mgcp_client_handle_response(struct mgcp_client *mgcp,
@@ -753,6 +755,8 @@
 				     struct mgcp_client_conf *conf)
 {
 	struct mgcp_client *mgcp;
+	struct reset_ep *reset_ep;
+	struct reset_ep *actual_reset_ep;
 
 	mgcp = talloc_zero(ctx, struct mgcp_client);
 	if (!mgcp)
@@ -783,6 +787,12 @@
 	}
 	LOGP(DLMGCP, LOGL_NOTICE, "MGCP client: using endpoint domain '@%s'\n", mgcp_client_endpoint_domain(mgcp));
 
+	INIT_LLIST_HEAD(&mgcp->actual.reset_epnames);
+	llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
+		actual_reset_ep = talloc_memdup(mgcp, reset_ep, sizeof(*reset_ep));
+		llist_add_tail(&actual_reset_ep->list, &mgcp->actual.reset_epnames);
+	}
+
 	return mgcp;
 }
 
@@ -822,13 +832,49 @@
 	return -EINVAL;
 }
 
-/*! Initalize client connection (opens socket only, no request is sent yet)
+/* Safely ignore the MGCP response to the DLCX sent via _mgcp_client_send_dlcx() */
+static void _ignore_mgcp_response(struct mgcp_response *response, void *priv) { }
+
+/* Format DLCX message (fire and forget) and send it off to the MGW */
+static void _mgcp_client_send_dlcx(struct mgcp_client *mgcp, const char *epname)
+{
+	struct msgb *msgb_dlcx;
+	struct mgcp_msg mgcp_msg_dlcx = {
+		.verb = MGCP_VERB_DLCX,
+		.presence = MGCP_MSG_PRESENCE_ENDPOINT,
+	};
+	osmo_strlcpy(mgcp_msg_dlcx.endpoint, epname, sizeof(mgcp_msg_dlcx.endpoint));
+	msgb_dlcx = mgcp_msg_gen(mgcp, &mgcp_msg_dlcx);
+	mgcp_client_tx(mgcp, msgb_dlcx, &_ignore_mgcp_response, NULL);
+}
+
+static const char *_mgcp_client_name_append_domain(const struct mgcp_client *mgcp, const char *name)
+{
+	static char endpoint[MGCP_ENDPOINT_MAXLEN];
+	int rc;
+
+	rc = snprintf(endpoint, sizeof(endpoint), "%s@%s", name, mgcp_client_endpoint_domain(mgcp));
+	if (rc > sizeof(endpoint) - 1) {
+		LOGP(DLMGCP, LOGL_ERROR, "MGCP endpoint exceeds maximum length of %zu: '%s@%s'\n",
+		     sizeof(endpoint) - 1, name, mgcp_client_endpoint_domain(mgcp));
+		return NULL;
+	}
+	if (rc < 1) {
+		LOGP(DLMGCP, LOGL_ERROR, "Cannot compose MGCP endpoint name\n");
+		return NULL;
+	}
+	return endpoint;
+}
+
+/*! Initialize client connection (opens socket)
  *  \param[in,out] mgcp MGCP client descriptor.
  *  \returns 0 on success, -EINVAL on error. */
 int mgcp_client_connect(struct mgcp_client *mgcp)
 {
 	struct osmo_wqueue *wq;
 	int rc;
+	struct reset_ep *reset_ep;
+	const char *epname;
 
 	if (!mgcp) {
 		LOGP(DLMGCP, LOGL_FATAL, "MGCPGW client not initialized properly\n");
@@ -851,9 +897,15 @@
 		goto error_close_fd;
 	}
 
-
 	LOGP(DLMGCP, LOGL_INFO, "MGCP GW connection: %s\n", osmo_sock_get_name2(wq->bfd.fd));
 
+	/* If configured, send a DLCX message to the endpoints that are configured to
+	 * be reset on startup. Usually this is a wildcarded endpoint. */
+	llist_for_each_entry(reset_ep, &mgcp->actual.reset_epnames, list) {
+		epname = _mgcp_client_name_append_domain(mgcp, reset_ep->name);
+		LOGP(DLMGCP, LOGL_INFO, "MGCP GW sending DLCX to: %s\n", epname);
+		_mgcp_client_send_dlcx(mgcp, epname);
+	}
 	return 0;
 error_close_fd:
 	close(wq->bfd.fd);
@@ -893,24 +945,6 @@
 	return mgcp->actual.endpoint_domain_name[0] ? mgcp->actual.endpoint_domain_name : "mgw";
 }
 
-static const char *_mgcp_client_name_append_domain(const struct mgcp_client *mgcp, char *name)
-{
-	static char endpoint[MGCP_ENDPOINT_MAXLEN];
-	int rc;
-
-	rc = snprintf(endpoint, sizeof(endpoint), "%s@%s", name, mgcp_client_endpoint_domain(mgcp));
-	if (rc > sizeof(endpoint) - 1) {
-		LOGP(DLMGCP, LOGL_ERROR, "MGCP endpoint exceeds maximum length of %zu: '%s@%s'\n",
-		     sizeof(endpoint) - 1, name, mgcp_client_endpoint_domain(mgcp));
-		return NULL;
-	}
-	if (rc < 1) {
-		LOGP(DLMGCP, LOGL_ERROR, "Cannot compose MGCP endpoint name\n");
-		return NULL;
-	}
-	return endpoint;
-}
-
 /*! Compose endpoint name for a wildcarded request to the virtual trunk
  *  \param[in] mgcp MGCP client descriptor.
  *  \returns string containing the endpoint name (e.g. rtpbridge\*@mgw) */
diff --git a/src/libosmo-mgcp-client/mgcp_client_vty.c b/src/libosmo-mgcp-client/mgcp_client_vty.c
index cc8db5d..1126c5c 100644
--- a/src/libosmo-mgcp-client/mgcp_client_vty.c
+++ b/src/libosmo-mgcp-client/mgcp_client_vty.c
@@ -29,6 +29,7 @@
 #include <osmocom/core/utils.h>
 
 #include <osmocom/mgcp_client/mgcp_client.h>
+#include <osmocom/mgcp_client/mgcp_client_internal.h>
 
 #define MGW_STR MGCP_CLIENT_MGW_STR
 
@@ -155,10 +156,72 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_mgw_reset_ep_name,
+      cfg_mgw_reset_ep_name_cmd,
+      "mgw reset-endpoint NAME",
+      MGW_STR "Add an endpoint name that should be reset (DLCX) on connect to the reset-endpoint list,"
+      "e.g. 'rtpbridge/*'\n"
+      "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
+{
+	int rc;
+	struct reset_ep *reset_ep;
+
+	/* stop when the address is already in the list */
+	llist_for_each_entry(reset_ep, &global_mgcp_client_conf->reset_epnames, list) {
+		if (strcmp(argv[0], reset_ep->name) == 0) {
+			vty_out(vty, "%% duplicate endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
+			return CMD_WARNING;
+		}
+	}
+
+	/* the domain name is not part of the actual endpoint name */
+	if (strchr(argv[0], '@')) {
+		vty_out(vty, "%% the endpoint name must be given without domain name ('%s')%s",
+			argv[0], VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	reset_ep = talloc_zero(global_mgcp_client_ctx, struct reset_ep);
+	OSMO_ASSERT(reset_ep);
+
+	rc = osmo_strlcpy(reset_ep->name, argv[0], sizeof(reset_ep->name));
+	if (rc >= sizeof(reset_ep->name)) {
+		vty_out(vty, "%% Error: 'mgw reset-endpoint' name too long, max length is %zu: '%s'%s",
+			sizeof(reset_ep->name) - 1, argv[0], VTY_NEWLINE);
+		talloc_free(reset_ep);
+		return CMD_WARNING;
+	}
+
+	llist_add_tail(&reset_ep->list, &global_mgcp_client_conf->reset_epnames);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgw_no_reset_ep_name,
+      cfg_mgw_no_reset_ep_name_cmd,
+      "no mgw reset-endpoint NAME",
+      MGW_STR "remove an endpoint name from the reset-endpoint list, e.g. 'rtpbridge/*'\n"
+      "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
+{
+	struct reset_ep *reset_ep;
+
+	llist_for_each_entry(reset_ep, &global_mgcp_client_conf->reset_epnames, list) {
+		if (strcmp(argv[0], reset_ep->name) == 0) {
+			llist_del(&reset_ep->list);
+			talloc_free(reset_ep);
+			return CMD_SUCCESS;
+		}
+	}
+
+	vty_out(vty, "%% no such endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
+	return CMD_WARNING;
+}
+
 int mgcp_client_config_write(struct vty *vty, const char *indent)
 {
 	const char *addr;
 	int port;
+	struct reset_ep *reset_ep;
 
 	addr = global_mgcp_client_conf->local_addr;
 	if (addr)
@@ -182,6 +245,9 @@
 		vty_out(vty, "%smgw endpoint-domain %s%s", indent,
 			global_mgcp_client_conf->endpoint_domain_name, VTY_NEWLINE);
 
+	llist_for_each_entry(reset_ep, &global_mgcp_client_conf->reset_epnames, list)
+		vty_out(vty, "%smgw reset-endpoint %s%s", indent, reset_ep->name, VTY_NEWLINE);
+
 	return CMD_SUCCESS;
 }
 
@@ -197,6 +263,8 @@
 	install_lib_element(node, &cfg_mgw_endpoint_range_cmd);
 	install_lib_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
 	install_lib_element(node, &cfg_mgw_endpoint_domain_name_cmd);
+	install_lib_element(node, &cfg_mgw_reset_ep_name_cmd);
+	install_lib_element(node, &cfg_mgw_no_reset_ep_name_cmd);
 
 	/* deprecated 'mgcpgw' commands */
 	install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/25008
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-mgw
Gerrit-Branch: master
Gerrit-Change-Id: I47e7ff858d5067b46d52329be5f362ff61c0dff8
Gerrit-Change-Number: 25008
Gerrit-PatchSet: 17
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-CC: neels <nhofmeyr at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210817/00378f94/attachment.htm>


More information about the gerrit-log mailing list