pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-mgw/+/39740?usp=email )
Change subject: mgw: Split DLCX read-only validations into its own function
......................................................................
mgw: Split DLCX read-only validations into its own function
Similar to what's already done in CRCX and MDXC.
Change-Id: I3d86f0cbeacc7c0cd69809f898714a76d3b86ed0
---
M src/libosmo-mgcp/mgcp_protocol.c
1 file changed, 50 insertions(+), 28 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/40/39740/1
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index 6a731a3..237f2bf 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -1073,6 +1073,49 @@
return create_err_response(endp, endp, error_code, "MDCX", pdata->trans);
}
+/* Read-only checks for parsed DLCX request, applied to existing found conn.
+ * Returns negative MGCP error code on failure, 0 on scucess.
+ * NOTE: rq->endp may be NULL here! */
+static int validate_parsed_dlcx(struct mgcp_request_data *rq)
+{
+ struct mgcp_parse_data *pdata = rq->pdata;
+ struct mgcp_parse_hdr_pars *hpars = &pdata->hpars;
+ struct rate_ctr_group *rate_ctrs = rq->trunk->ratectr.mgcp_dlcx_ctr_group;
+ int rc;
+
+ if (hpars->callid) {
+ /* If we have no endpoint, but a call id in the request, then this request cannot be handled */
+ if (!rq->endp) {
+ LOGPTRUNK(rq->trunk, DLMGCP, LOGL_NOTICE,
+ "cannot handle requests with call-id (C) without endpoint -- abort!");
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
+ return -539;
+ }
+ if (!(rq->endp->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID) &&
+ mgcp_verify_call_id(rq->endp, hpars->callid) != 0) {
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CALLID));
+ return -516;
+ }
+ }
+
+ if (hpars->connid) {
+ /* If we have no endpoint, but a connection id in the request, then this request cannot be handled */
+ if (!rq->endp) {
+ LOGPTRUNK(rq->trunk, DLMGCP, LOGL_NOTICE,
+ "cannot handle requests with conn-id (I) without endpoint -- abort!");
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
+ return -539;
+ }
+ if ((rc = mgcp_verify_ci(rq->endp, hpars->connid)) != 0) {
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CONNID));
+ return -rc;
+ }
+ }
+
+ /* Everything fine, continue */
+ return 0;
+}
+
/* DLCX command handler, processes the received command */
static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
{
@@ -1130,39 +1173,18 @@
if (rc < 0)
return create_err_response(rq->trunk, NULL, -rc, "DLCX", pdata->trans);
- if (hpars->callid) {
- /* If we have no endpoint, but a call id in the request, then this request cannot be handled */
- if (!endp) {
- LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
- "cannot handle requests with call-id (C) without endpoint -- abort!");
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
- return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans);
- }
- if (!(endp->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID) &&
- mgcp_verify_call_id(endp, hpars->callid) != 0) {
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CALLID));
- return create_err_response(endp, endp, 516, "DLCX", pdata->trans);
- }
- }
-
- if (hpars->connid) {
- /* If we have no endpoint, but a connection id in the request, then this request cannot be handled */
- if (!endp) {
- LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
- "cannot handle requests with conn-id (I) without endpoint -- abort!");
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
- return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans);
- }
- if ((rc = mgcp_verify_ci(endp, hpars->connid)) != 0) {
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CONNID));
- return create_err_response(endp, endp, rc, "DLCX", pdata->trans);
- }
- }
+ rc = validate_parsed_dlcx(rq);
+ if (rc < 0)
+ return create_err_response(rq->trunk, NULL, -rc, "DLCX", pdata->trans);
/* The logic does not permit to go past this point without having the
* the endp pointer populated. */
OSMO_ASSERT(endp);
+ /*****************************************************************************
+ * From here on below we start, delete conn and potentially release endpoint.
+ *****************************************************************************/
+
/* When no connection id is supplied, we will interpret this as a
* wildcarded DLCX that refers to the selected endpoint. This means
* that we drop all connections on that specific endpoint at once.
--
To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/39740?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-mgw
Gerrit-Branch: master
Gerrit-Change-Id: I3d86f0cbeacc7c0cd69809f898714a76d3b86ed0
Gerrit-Change-Number: 39740
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Attention is currently required from: dexter.
Hello Jenkins Builder, fixeria, laforge, pespin,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39692?usp=email
to look at the new patch set (#3).
The following approvals got outdated and were removed:
Verified+1 by Jenkins Builder
The change is no longer submittable: Verified is unsatisfied now.
Change subject: HTTP_Adapter: add missing omit qualifiers
......................................................................
HTTP_Adapter: add missing omit qualifiers
On some function in the HTTP_Adapter module, the (omit)
qualifiers are missing.
Related: SYS#7339
Change-Id: I985021852cbe2bcce60b1466e8ec9c3820a0c0f8
---
M library/HTTP_Adapter.ttcn
1 file changed, 5 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/92/39692/3
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39692?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I985021852cbe2bcce60b1466e8ec9c3820a0c0f8
Gerrit-Change-Number: 39692
Gerrit-PatchSet: 3
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-Attention: dexter <pmaier(a)sysmocom.de>
pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-mgw/+/39736?usp=email )
Change subject: mgw: Split CRCX read-only validations into its own function
......................................................................
mgw: Split CRCX read-only validations into its own function
The SDP parsing is moved to a step beforehand, so that validation of
full message can be done in a subsequent step. That validation step is
moved into a function to give some air to handle_create_con() and easily
spot the logic.
The logic based on force_realloc is split so that code modifying the
object is moved to the later update step.
Change-Id: I639ad0a25a0af4a4637045ca8bf61e436a789426
---
M src/libosmo-mgcp/mgcp_protocol.c
1 file changed, 108 insertions(+), 80 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/36/39736/1
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index 49a4e83..0e0f9dd 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -567,6 +567,87 @@
return 534;
}
+/* Read-only checks for parsed CRCX request.
+ * Returns negative MGCP error code on failure, 0 on scucess. */
+static int validate_parsed_crcx(struct mgcp_request_data *rq)
+{
+ struct mgcp_parse_data *pdata = rq->pdata;
+ struct mgcp_trunk *trunk = rq->trunk;
+ struct mgcp_endpoint *endp = rq->endp;
+ struct mgcp_parse_hdr_pars *hpars = &pdata->hpars;
+ struct rate_ctr_group *rate_ctrs = trunk->ratectr.mgcp_crcx_ctr_group;
+
+ /* Check parameters */
+ if (!hpars->callid) {
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR,
+ "CRCX: insufficient parameters, missing callid\n");
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_MISSING_CALLID));
+ return -516;
+ }
+
+ if (hpars->mode == MGCP_CONN_NONE) {
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR,
+ "CRCX: insufficient parameters, invalid mode\n");
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_MODE));
+ return -517;
+ }
+
+ /* It is illegal to send a connection identifier
+ * together with a CRCX, the MGW will assign the
+ * connection identifier by itself on CRCX */
+ if (hpars->connid) {
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: 'I: %s' not expected!\n", hpars->connid);
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION));
+ return -523;
+ }
+
+ /* Reject osmux if disabled by config */
+ if (trunk->cfg->osmux.usage == OSMUX_USAGE_OFF &&
+ hpars->remote_osmux_cid != MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET) {
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: Request with Osmux but it is disabled by config!\n");
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_NO_OSMUX));
+ return -511;
+ }
+ /* Reject non-osmux if required by config */
+ if (trunk->cfg->osmux.usage == OSMUX_USAGE_ONLY &&
+ hpars->remote_osmux_cid == MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET) {
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: Request without Osmux but it is required by config!\n");
+ return -517;
+ }
+
+ /* Read-only checks here, force_realloc case done out of there afterwards.*/
+ if (!trunk->force_realloc) {
+ /* Check if we are able to accept the creation of another connection */
+ if (mgcp_endp_is_full(endp)) {
+ /* There is no more room for a connection, leave
+ * everything as it is and return with an error */
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: endpoint full, max. %d connections allowed!\n",
+ endp->type->max_conns);
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_LIMIT_EXCEEDED));
+ return -540;
+ }
+
+ /* Check if this endpoint already serves a call, if so, check if the
+ * callids match up so that we are sure that this is our call.
+ * Do check only if endpoint was (or is by current CRCX) configured
+ * to explicitly ignore it ("X-Osmo-IGN: C").
+ */
+ if (endp->callid &&
+ !((endp->x_osmo_ign | hpars->x_osmo_ign) & MGCP_X_OSMO_IGN_CALLID) &&
+ mgcp_verify_call_id(endp, hpars->callid)) {
+ /* This is not our call, leave everything as it is and
+ * return with an error. */
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: already seized by other call (%s)\n",
+ endp->callid);
+ rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNKNOWN_CALLID));
+ return -400;
+ }
+ }
+
+ /* Everything fine, continue */
+ return 0;
+}
+
/* CRCX command handler, processes the received command */
static struct msgb *handle_create_con(struct mgcp_request_data *rq)
{
@@ -589,6 +670,7 @@
return create_err_response(rq->cfg, NULL, 502, "CRCX", pdata->trans);
}
+ /* rq->trunk is available (non-null) from here on. */
rate_ctrs = trunk->ratectr.mgcp_crcx_ctr_group;
/* we must have a free ep */
@@ -617,30 +699,6 @@
return create_err_response(rq->trunk, NULL, -rc, "CRCX", pdata->trans);
}
- /* Check parameters */
- if (!hpars->callid) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR,
- "CRCX: insufficient parameters, missing callid\n");
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_MISSING_CALLID));
- return create_err_response(endp, endp, 516, "CRCX", pdata->trans);
- }
-
- if (hpars->mode == MGCP_CONN_NONE) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR,
- "CRCX: insufficient parameters, invalid mode\n");
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_MODE));
- return create_err_response(endp, endp, 517, "CRCX", pdata->trans);
- }
-
- /* It is illegal to send a connection identifier
- * together with a CRCX, the MGW will assign the
- * connection identifier by itself on CRCX */
- if (hpars->connid) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: 'I: %s' not expected!\n", hpars->connid);
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION));
- return create_err_response(endp, endp, 523, "CRCX", pdata->trans);
- }
-
/* Parse SDP if found: */
if (hpars->have_sdp) {
rc = mgcp_parse_sdp_data(pdata);
@@ -650,67 +708,37 @@
}
}
- /* Reject osmux if disabled by config */
- if (trunk->cfg->osmux.usage == OSMUX_USAGE_OFF &&
- hpars->remote_osmux_cid != MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: Request with Osmux but it is disabled by config!\n");
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_NO_OSMUX));
- return create_err_response(endp, endp, 511, "CRCX", pdata->trans);
- }
- /* Reject non-osmux if required by config */
- if (trunk->cfg->osmux.usage == OSMUX_USAGE_ONLY &&
- hpars->remote_osmux_cid == MGCP_PARSE_HDR_PARS_OSMUX_CID_UNSET) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: Request without Osmux but it is required by config!\n");
- return create_err_response(endp, endp, 517, "CRCX", pdata->trans);
- }
-
- /* Check if we are able to accept the creation of another connection */
- if (mgcp_endp_is_full(endp)) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR,
- "CRCX: endpoint full, max. %i connections allowed!\n",
- endp->type->max_conns);
- if (trunk->force_realloc) {
- /* There is no more room for a connection, make some
- * room by blindly tossing the oldest of the two two
- * connections */
- mgcp_endp_free_conn_oldest(endp);
- OSMO_ASSERT(!mgcp_endp_is_full(endp));
- } else {
- /* There is no more room for a connection, leave
- * everything as it is and return with an error */
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_LIMIT_EXCEEDED));
- return create_err_response(endp, endp, 540, "CRCX", pdata->trans);
- }
- }
-
- /* Check if this endpoint already serves a call, if so, check if the
- * callids match up so that we are sure that this is our call.
- * Do check only if endpoint was (or is by current CRCX) configured
- * to explicitly ignore it ("X-Osmo-IGN: C").
- */
- if (endp->callid &&
- !((endp->x_osmo_ign | hpars->x_osmo_ign) & MGCP_X_OSMO_IGN_CALLID) &&
- mgcp_verify_call_id(endp, hpars->callid)) {
- LOGPENDP(endp, DLMGCP, LOGL_ERROR,
- "CRCX: already seized by other call (%s)\n",
- endp->callid);
- if (trunk->force_realloc)
- /* This is not our call, toss everything by releasing
- * the entire endpoint. (rude!) */
- mgcp_endp_release(endp);
- else {
- /* This is not our call, leave everything as it is and
- * return with an error. */
- rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNKNOWN_CALLID));
- return create_err_response(endp, endp, 400, "CRCX", pdata->trans);
- }
- }
+ rc = validate_parsed_crcx(rq);
+ if (rc < 0)
+ return create_err_response(endp, endp, -rc, "CRCX", pdata->trans);
/*******************************************************************
* Allocate and update endpoint and conn.
- * From here on below we start updating endpoing and creating conn:
+ * From here on below we start updating endpoint and creating conn:
*******************************************************************/
+ if (trunk->force_realloc) {
+ /* Check if we are able to accept the creation of another connection */
+ if (mgcp_endp_is_full(endp)) {
+ /* There is no more room for a connection, make some
+ * room by blindly tossing the oldest of the two two
+ * connections */
+ LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: endpoint full, max. %d connections allowed!\n",
+ endp->type->max_conns);
+ mgcp_endp_free_conn_oldest(endp);
+ OSMO_ASSERT(!mgcp_endp_is_full(endp));
+ }
+
+ /* Check if this endpoint already serves a call and then check if the callids match up */
+ if (endp->callid &&
+ !((endp->x_osmo_ign | hpars->x_osmo_ign) & MGCP_X_OSMO_IGN_CALLID) &&
+ mgcp_verify_call_id(endp, hpars->callid)) {
+ /* This is not our call, toss everything by releasing
+ * the entire endpoint. (rude!) */
+ mgcp_endp_release(endp);
+ }
+ }
+
/* Update endp->x_osmo_ign: */
endp->x_osmo_ign |= hpars->x_osmo_ign;
--
To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/39736?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-mgw
Gerrit-Branch: master
Gerrit-Change-Id: I639ad0a25a0af4a4637045ca8bf61e436a789426
Gerrit-Change-Number: 39736
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
osmith has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39735?usp=email )
Change subject: testenv: use --autoreconf-in-src-copy by default
......................................................................
testenv: use --autoreconf-in-src-copy by default
Pass --autoreconf-in-src-copy to osmo-dev's gen_makefile.py by default,
so we can always avoid errors related to:
* running "./configure" in-tree and out-of-tree (results in "configure:
error: source directory already configured; run "make distclean" there
first")
* running "./configure" / "autoreconf" with different autotools versions
(on host system and in podman container)
I've kept is as experimental flag at first for better testing, but make
it the default now as it seems to work reliably.
The old make dir is cleaned up when the user runs "./testenv.py clean"
the next time.
Related: osmo-dev I18ac50e3441df81e1fe7d8d5321df7e80ab9c650
Change-Id: I41e1fb534e253ddb43f266d73485b83259a8aa40
---
M _testenv/testenv/__init__.py
M _testenv/testenv/osmo_dev.py
M _testenv/testenv/requirements.py
3 files changed, 9 insertions(+), 16 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/35/39735/1
diff --git a/_testenv/testenv/__init__.py b/_testenv/testenv/__init__.py
index 4a925bb..c1991ca 100644
--- a/_testenv/testenv/__init__.py
+++ b/_testenv/testenv/__init__.py
@@ -170,14 +170,6 @@
default=ccache_dir_default,
)
- group = sub_run.add_argument_group("experimental options")
- group.add_argument(
- "-A",
- "--autoreconf-in-src-copy",
- action="store_true",
- help="run autoreconf in a copy of the source dir, avoids 'run make distclean' errors",
- )
-
sub.add_parser("clean", help="clean previous build artifacts")
args = parser.parse_args()
diff --git a/_testenv/testenv/osmo_dev.py b/_testenv/testenv/osmo_dev.py
index 8748b93..695ca0d 100644
--- a/_testenv/testenv/osmo_dev.py
+++ b/_testenv/testenv/osmo_dev.py
@@ -73,14 +73,10 @@
os.path.join(testenv.args.cache, "host/usr"),
]
- if testenv.args.autoreconf_in_src_copy:
- # Use a different make dir, so we don't have unexpected behavior when
- # the user already ran autoreconf or ./configure through osmo-dev with
- # the previous make dir, without --autoreconf-in-src-copy.
- make_dir += "2"
- extra_opts += [
- "--autoreconf-in-src-copy",
- ]
+ # Make dirs created without passing --autoreconf-in-src-copy to
+ # gen_makefile.py (as previous versions of testenv did) are incompatible.
+ # Add the "2" to avoid potential conflicts.
+ make_dir += "2"
cmd = [
"./gen_makefile.py",
@@ -103,6 +99,7 @@
"no_systemd.opts",
"werror.opts",
os.path.join(testenv.data_dir, "osmo-dev/osmo-bts-trx.opts"),
+ "--autoreconf-in-src-copy",
] + extra_opts
cwd = get_osmo_dev_dir()
diff --git a/_testenv/testenv/requirements.py b/_testenv/testenv/requirements.py
index 4973f6e..5405f50 100644
--- a/_testenv/testenv/requirements.py
+++ b/_testenv/testenv/requirements.py
@@ -44,6 +44,10 @@
"lddtree",
"qemu-system-x86_64",
]
+ if not testenv.args.binary_repo:
+ programs += [
+ "rsync",
+ ]
abort = False
for program in programs:
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39735?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I41e1fb534e253ddb43f266d73485b83259a8aa40
Gerrit-Change-Number: 39735
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>