<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-mgw/+/18898">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Jenkins Builder: Verified
neels: Looks good to me, but someone else must approve
laforge: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">endp: add E1 endpoint interlocking<br><br>E1 endpoint names also represent different rates, this may mean that<br>some rate / subslot combinations are not possible because they overlap<br>within nthe timeslot. When the equipment (BSC) is properly configured,<br>this will be no problem, however invalid configuration may cause the<br>selection of overlapping endpoints and this needs to be prevented, and<br>logged. Also rate counters need to be in place.<br><br>Change-Id: I18e90b10648a7e504371179ad144645fc82e1c27<br>Related: OS#2547<br>---<br>M include/osmocom/mgcp/mgcp_endp.h<br>M include/osmocom/mgcp/mgcp_ratectr.h<br>M src/libosmo-mgcp/mgcp_endp.c<br>M src/libosmo-mgcp/mgcp_protocol.c<br>M src/libosmo-mgcp/mgcp_ratectr.c<br>M src/libosmo-mgcp/mgcp_vty.c<br>6 files changed, 301 insertions(+), 27 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/mgcp/mgcp_endp.h b/include/osmocom/mgcp/mgcp_endp.h</span><br><span>index 0f9110c..a58053a 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp_endp.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp_endp.h</span><br><span>@@ -110,3 +110,4 @@</span><br><span> const struct mgcp_trunk *trunk);</span><br><span> struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,</span><br><span> struct mgcp_config *cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+bool mgcp_endp_avail(struct mgcp_endpoint *endp);</span><br><span>diff --git a/include/osmocom/mgcp/mgcp_ratectr.h b/include/osmocom/mgcp/mgcp_ratectr.h</span><br><span>index a579f5b..d0bc628 100644</span><br><span>--- a/include/osmocom/mgcp/mgcp_ratectr.h</span><br><span>+++ b/include/osmocom/mgcp/mgcp_ratectr.h</span><br><span>@@ -28,6 +28,7 @@</span><br><span> MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS,</span><br><span> MGCP_CRCX_FAIL_CODEC_NEGOTIATION,</span><br><span> MGCP_CRCX_FAIL_BIND_PORT,</span><br><span style="color: hsl(120, 100%, 40%);">+ MGCP_CRCX_FAIL_AVAIL,</span><br><span> };</span><br><span> </span><br><span> /* Global MCGP MDCX related rate counters */</span><br><span>@@ -45,7 +46,8 @@</span><br><span> MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC,</span><br><span> MGCP_MDCX_FAIL_START_RTP,</span><br><span> MGCP_MDCX_FAIL_REJECTED_BY_POLICY,</span><br><span style="color: hsl(0, 100%, 40%);">- MGCP_MDCX_DEFERRED_BY_POLICY</span><br><span style="color: hsl(120, 100%, 40%);">+ MGCP_MDCX_DEFERRED_BY_POLICY,</span><br><span style="color: hsl(120, 100%, 40%);">+ MGCP_MDCX_FAIL_AVAIL,</span><br><span> };</span><br><span> </span><br><span> /* Global MCGP DLCX related rate counters */</span><br><span>@@ -58,6 +60,7 @@</span><br><span> MGCP_DLCX_FAIL_UNHANDLED_PARAM,</span><br><span> MGCP_DLCX_FAIL_REJECTED_BY_POLICY,</span><br><span> MGCP_DLCX_DEFERRED_BY_POLICY,</span><br><span style="color: hsl(120, 100%, 40%);">+ MGCP_DLCX_FAIL_AVAIL,</span><br><span> };</span><br><span> </span><br><span> /* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_endp.c b/src/libosmo-mgcp/mgcp_endp.c</span><br><span>index 94d4083..5e7bebb 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_endp.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_endp.c</span><br><span>@@ -25,6 +25,33 @@</span><br><span> #include <osmocom/mgcp/mgcp_endp.h></span><br><span> #include <osmocom/mgcp/mgcp_trunk.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define E1_TIMESLOTS 32</span><br><span style="color: hsl(120, 100%, 40%);">+#define E1_RATE_MAX 64</span><br><span style="color: hsl(120, 100%, 40%);">+#define E1_OFFS_MAX 8</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* A 64k timeslot on an E1 line can be subdevied into the following</span><br><span style="color: hsl(120, 100%, 40%);">+ * subslot combinations:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * subslot: offset:</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ ][ ][ 16k ][8k_subslot] 0</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ ][ 32k ][_subslot__][8k_subslot] 1</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ ][ subslot ][ 16k ][8k_subslot] 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ 64k ][__________][_subslot__][8k_subslot] 3</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ timeslot ][ ][ 16k ][8k_subslot] 4</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ ][ 32K ][_subslot__][8k_subslot] 5</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ ][ subslot ][ 16k ][8k_subslot] 6</span><br><span style="color: hsl(120, 100%, 40%);">+ * [ ][ ][ subslot ][8k_subslot] 7</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Since overlapping assignment of subslots is not possible there is a limited</span><br><span style="color: hsl(120, 100%, 40%);">+ * set of subslot assignments possible. The e1_rates array lists the possible</span><br><span style="color: hsl(120, 100%, 40%);">+ * assignments as depicted above. Also each subslot assignment comes along with</span><br><span style="color: hsl(120, 100%, 40%);">+ * a bit offset in the E1 bitstream. The e1_offsets arrays lists the bit</span><br><span style="color: hsl(120, 100%, 40%);">+ * offsets. */</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t e1_rates[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t e1_offsets[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Endpoint typeset definition */</span><br><span> const struct mgcp_endpoint_typeset ep_typeset = {</span><br><span> /* Specify endpoint properties for RTP endpoint */</span><br><span>@@ -53,35 +80,13 @@</span><br><span> static char *gen_e1_epname(void *ctx, uint8_t trunk_nr, uint8_t ts_nr,</span><br><span> uint8_t ss_nr)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- /* A 64k timeslot on an E1 line can be subdevied into the following</span><br><span style="color: hsl(0, 100%, 40%);">- * subslot combinations:</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * subslot: offset:</span><br><span style="color: hsl(0, 100%, 40%);">- * [ ][ ][ 16k ][8k_subslot] 0</span><br><span style="color: hsl(0, 100%, 40%);">- * [ ][ 32k ][_subslot__][8k_subslot] 1</span><br><span style="color: hsl(0, 100%, 40%);">- * [ ][ subslot ][ 16k ][8k_subslot] 2</span><br><span style="color: hsl(0, 100%, 40%);">- * [ 64k ][__________][_subslot__][8k_subslot] 3</span><br><span style="color: hsl(0, 100%, 40%);">- * [ timeslot ][ ][ 16k ][8k_subslot] 4</span><br><span style="color: hsl(0, 100%, 40%);">- * [ ][ 32K ][_subslot__][8k_subslot] 5</span><br><span style="color: hsl(0, 100%, 40%);">- * [ ][ subslot ][ 16k ][8k_subslot] 6</span><br><span style="color: hsl(0, 100%, 40%);">- * [ ][ ][ subslot ][8k_subslot] 7</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Since overlapping assignment of subsolts is not possible there is</span><br><span style="color: hsl(0, 100%, 40%);">- * a limited set of subsolt assignments possible. The rates array</span><br><span style="color: hsl(0, 100%, 40%);">- * lists the possible assignments as depicted above. Also each subslot</span><br><span style="color: hsl(0, 100%, 40%);">- * assignment comes along with a bit offset in the E1 bitstream. The</span><br><span style="color: hsl(0, 100%, 40%);">- * offsets arrays lists the bit offsets. */</span><br><span style="color: hsl(0, 100%, 40%);">- static const uint8_t rates[] =</span><br><span style="color: hsl(0, 100%, 40%);">- { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8 };</span><br><span style="color: hsl(0, 100%, 40%);">- static const uint8_t offsets[] =</span><br><span style="color: hsl(0, 100%, 40%);">- { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };</span><br><span> unsigned int rate;</span><br><span> unsigned int offset;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(ss_nr < sizeof(rates));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ss_nr < sizeof(e1_rates));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- rate = rates[ss_nr];</span><br><span style="color: hsl(0, 100%, 40%);">- offset = offsets[ss_nr];</span><br><span style="color: hsl(120, 100%, 40%);">+ rate = e1_rates[ss_nr];</span><br><span style="color: hsl(120, 100%, 40%);">+ offset = e1_offsets[ss_nr];</span><br><span> </span><br><span> return talloc_asprintf(ctx, "%s%u/s-%u/su%u-%u",</span><br><span> MGCP_ENDPOINT_PREFIX_E1_TRUNK, trunk_nr, ts_nr, rate, offset);</span><br><span>@@ -213,7 +218,9 @@</span><br><span> </span><br><span> for (i = 0; i < trunk->number_endpoints; i++) {</span><br><span> endp = trunk->endpoints[i];</span><br><span style="color: hsl(0, 100%, 40%);">- if (endp->callid == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ /* A free endpoint must not serve a call already and it must</span><br><span style="color: hsl(120, 100%, 40%);">+ * be available. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (endp->callid == NULL && mgcp_endp_avail(endp))</span><br><span> return endp;</span><br><span> }</span><br><span> </span><br><span>@@ -362,3 +369,247 @@</span><br><span> *cause = 0;</span><br><span> return endp;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Get the E1 timeslot number from a given E1 endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+ * (e.g. ds/e1-0/s-30/su16-4), returns 0xff on error. */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t e1_ts_nr_from_epname(const char *epname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[MGCP_ENDPOINT_MAXLEN + 1];</span><br><span style="color: hsl(120, 100%, 40%);">+ char *save_ptr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf_ptr = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *token;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned long int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ strncpy(buf, epname, MGCP_ENDPOINT_MAXLEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ token = strtok_r(buf_ptr, "/", &save_ptr);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf_ptr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!token)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp(token, "s-", 2) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ res = strtoul(token + 2, NULL, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (errno == ERANGE || res > E1_TIMESLOTS)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ return (uint8_t) res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Get the E1 timeslot number from a given E1 endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+ * (e.g. ds/e1-0/s-30/su16-4), returns 0xff on error. */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t e1_rate_from_epname(const char *epname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[MGCP_ENDPOINT_MAXLEN + 1];</span><br><span style="color: hsl(120, 100%, 40%);">+ char *save_ptr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf_ptr = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *token;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned long int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ strncpy(buf, epname, MGCP_ENDPOINT_MAXLEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ token = strtok_r(buf_ptr, "/", &save_ptr);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf_ptr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!token)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp(token, "su", 2) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ res = strtoul(token + 2, NULL, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (errno == ERANGE || res > E1_RATE_MAX)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Make sure the rate is a valid rate */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < sizeof(e1_rates); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res == e1_rates[i])</span><br><span style="color: hsl(120, 100%, 40%);">+ return (uint8_t) res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Get the E1 bitstream offset from a given E1 endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+ * (e.g. ds/e1-0/s-30/su16-4), returns 0xff on error. */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t e1_offs_from_epname(const char *epname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[MGCP_ENDPOINT_MAXLEN + 1];</span><br><span style="color: hsl(120, 100%, 40%);">+ char *save_ptr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf_ptr = buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *token;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned long int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ strncpy(buf, epname, MGCP_ENDPOINT_MAXLEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ token = strtok_r(buf_ptr, "/", &save_ptr);</span><br><span style="color: hsl(120, 100%, 40%);">+ buf_ptr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!token)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strncmp(token, "su", 2) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ token = strstr(token, "-");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!token)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ token += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ errno = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ res = strtoul(token, NULL, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (errno == ERANGE || res > E1_OFFS_MAX)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ return (uint8_t) res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Get the E1 subslot number (internal) from a given E1 endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+ * (e.g. ds/e1-0/s-30/su16-4), returns 0xff on error. */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t e1_ss_nr_from_epname(const char *epname)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t rate;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t offs;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rate = e1_rate_from_epname(epname);</span><br><span style="color: hsl(120, 100%, 40%);">+ offs = e1_offs_from_epname(epname);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_static_assert(sizeof(e1_rates) == sizeof(e1_offsets), e1_rates_e1_offsets_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < sizeof(e1_rates); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((e1_rates[i] == rate) && (e1_offsets[i] == offs))</span><br><span style="color: hsl(120, 100%, 40%);">+ return i;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Check if the selected E1 endpoint is avalable, which means that none of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the overlapping endpoints are currently serving a call. (if the system</span><br><span style="color: hsl(120, 100%, 40%);">+ * is properly configured such a situation should never ocurr!) */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool endp_avail_e1(struct mgcp_endpoint *endp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The following map shows the overlapping of the subslots and their</span><br><span style="color: hsl(120, 100%, 40%);">+ * respective rates. The numbers on the right running from top to bottom</span><br><span style="color: hsl(120, 100%, 40%);">+ * are the bit offsets in the whole 64k timeslot. The numbers inside the</span><br><span style="color: hsl(120, 100%, 40%);">+ * boxes symbolize the internal subslot number (array index) and the</span><br><span style="color: hsl(120, 100%, 40%);">+ * rate in the form: i:r where i is the subslot number and r the</span><br><span style="color: hsl(120, 100%, 40%);">+ * respective rate.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * +--------+--------+--------+--------+ 0</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 7:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | + 3:16k +--------+ 1</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 8:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | 1:32k +--------+--------+ 2</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 9:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | + 4:16k +--------+ 3</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 10:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | 0:64k +--------+--------+--------+ 4</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 11:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | + 5:16k +--------+ 5</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 12:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | 2:32k +--------+--------+ 6</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 13:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | + 6:16k +--------+ 7</span><br><span style="color: hsl(120, 100%, 40%);">+ * | | | | 14:8k |</span><br><span style="color: hsl(120, 100%, 40%);">+ * +--------+--------+--------+--------+ 8</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The following array contains tables with the subslot numbers that must be</span><br><span style="color: hsl(120, 100%, 40%);">+ * unused for each subslot. During this test we do not have to check the</span><br><span style="color: hsl(120, 100%, 40%);">+ * endpoint we need to verify, only the overlaps need to be checked. This is</span><br><span style="color: hsl(120, 100%, 40%);">+ * also the reason why the related subslot number is missing from each each</span><br><span style="color: hsl(120, 100%, 40%);">+ * line. */</span><br><span style="color: hsl(120, 100%, 40%);">+ const int8_t interlock_tab[15][16] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 3, 4, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 5, 6, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 1, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 11, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const int8_t *interlock;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ts_nr = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ss_nr = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *epname_check;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_endpoint *endp_check;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool available = true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* This function must only be used with E1 type endpoints! */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(endp->trunk->trunk_type == MGCP_TRUNK_E1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ts_nr = e1_ts_nr_from_epname(endp->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ss_nr = e1_ss_nr_from_epname(endp->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ts_nr == 0xff || ss_nr == 0xff) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "cannot check endpoint availability, endpoint name not parseable!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ interlock = interlock_tab[ss_nr];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < sizeof(interlock_tab[0]); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Detect row end */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (interlock[i] == -1)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Pick overlapping endpoint to check */</span><br><span style="color: hsl(120, 100%, 40%);">+ epname_check =</span><br><span style="color: hsl(120, 100%, 40%);">+ gen_e1_epname(endp, endp->trunk->trunk_nr, ts_nr,</span><br><span style="color: hsl(120, 100%, 40%);">+ interlock[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ endp_check = find_specific_endpoint(epname_check, endp->trunk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!endp_check) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "cannot check endpoint availability, overlapping endpoint:%s not found!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ epname_check);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(epname_check);</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(epname_check);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if overlapping endpoint currently serves another call</span><br><span style="color: hsl(120, 100%, 40%);">+ * (This is an exceptional situation, that should not occur</span><br><span style="color: hsl(120, 100%, 40%);">+ * in a properly configured environment!) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (endp_check->callid) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPENDP(endp, DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "endpoint unavailable - overlapping endpoint:%s already serves a call!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ endp_check->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ available = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return available;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! check if an endpoint is available for any kind of operation.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] endp endpoint to check.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns true if endpoint is avalable, false it is blocked for any reason. */</span><br><span style="color: hsl(120, 100%, 40%);">+bool mgcp_endp_avail(struct mgcp_endpoint *endp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (endp->trunk->trunk_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_VIRTUAL:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* There are no obstacles that may render a virtual trunk</span><br><span style="color: hsl(120, 100%, 40%);">+ * endpoint unusable, so virtual trunk endpoints are always</span><br><span style="color: hsl(120, 100%, 40%);">+ * available */</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MGCP_TRUNK_E1:</span><br><span style="color: hsl(120, 100%, 40%);">+ return endp_avail_e1(endp);</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(false);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>index 1e393e2..f2fc20c 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>@@ -747,6 +747,10 @@</span><br><span> int rc;</span><br><span> </span><br><span> LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mgcp_endp_avail(endp)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_AVAIL]);</span><br><span style="color: hsl(120, 100%, 40%);">+ return create_err_response(NULL, 501, "CRCX", p->trans);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> /* parse CallID C: and LocalParameters L: */</span><br><span> for_each_line(line, p->save) {</span><br><span>@@ -1004,6 +1008,11 @@</span><br><span> </span><br><span> LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: modifying existing connection ...\n");</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mgcp_endp_avail(endp)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_inc(&rate_ctrs->ctr[MGCP_MDCX_FAIL_AVAIL]);</span><br><span style="color: hsl(120, 100%, 40%);">+ return create_err_response(NULL, 501, "MDCX", p->trans);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Prohibit wildcarded requests */</span><br><span> if (endp->wildcarded_req) {</span><br><span> LOGPENDP(endp, DLMGCP, LOGL_ERROR,</span><br><span>@@ -1224,6 +1233,11 @@</span><br><span> LOGPENDP(endp, DLMGCP, LOGL_NOTICE,</span><br><span> "DLCX: deleting connection ...\n");</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mgcp_endp_avail(endp)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rate_ctr_inc(&rate_ctrs->ctr[MGCP_DLCX_FAIL_AVAIL]);</span><br><span style="color: hsl(120, 100%, 40%);">+ return create_err_response(NULL, 501, "DLCX", p->trans);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Prohibit wildcarded requests */</span><br><span> if (endp->wildcarded_req) {</span><br><span> LOGPENDP(endp, DLMGCP, LOGL_ERROR,</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_ratectr.c b/src/libosmo-mgcp/mgcp_ratectr.c</span><br><span>index 302786f..1a89c83 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_ratectr.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_ratectr.c</span><br><span>@@ -63,6 +63,7 @@</span><br><span> [MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS] = { "crcx:conn_opt", "connection options invalid." },</span><br><span> [MGCP_CRCX_FAIL_CODEC_NEGOTIATION] = { "crcx:codec_nego", "codec negotiation failure." },</span><br><span> [MGCP_CRCX_FAIL_BIND_PORT] = { "crcx:bind_port", "port bind failure." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_CRCX_FAIL_AVAIL] = { "crcx:unavailable", "endpoint unavailable." },</span><br><span> };</span><br><span> </span><br><span> const static struct rate_ctr_group_desc mgcp_crcx_ctr_group_desc = {</span><br><span>@@ -90,6 +91,7 @@</span><br><span> [MGCP_MDCX_FAIL_START_RTP] = { "mdcx:start_rtp_failure", "failure to start RTP processing." },</span><br><span> [MGCP_MDCX_FAIL_REJECTED_BY_POLICY] = { "mdcx:conn_rejected", "connection rejected by policy." },</span><br><span> [MGCP_MDCX_DEFERRED_BY_POLICY] = { "mdcx:conn_deferred", "connection deferred by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_MDCX_FAIL_AVAIL] = { "mdcx:unavailable", "endpoint unavailable." },</span><br><span> };</span><br><span> </span><br><span> const static struct rate_ctr_group_desc mgcp_mdcx_ctr_group_desc = {</span><br><span>@@ -111,6 +113,7 @@</span><br><span> [MGCP_DLCX_FAIL_UNHANDLED_PARAM] = { "dlcx:unhandled_param", "unhandled parameter in DLCX command." },</span><br><span> [MGCP_DLCX_FAIL_REJECTED_BY_POLICY] = { "dlcx:rejected", "connection deletion rejected by policy." },</span><br><span> [MGCP_DLCX_DEFERRED_BY_POLICY] = { "dlcx:deferred", "connection deletion deferred by policy." },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MGCP_DLCX_FAIL_AVAIL] = { "dlcx:unavailable", "endpoint unavailable." },</span><br><span> };</span><br><span> </span><br><span> const static struct rate_ctr_group_desc mgcp_dlcx_ctr_group_desc = {</span><br><span>diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c</span><br><span>index 938eef5..cbff700 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_vty.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_vty.c</span><br><span>@@ -199,6 +199,8 @@</span><br><span> </span><br><span> vty_out(vty, "%s trunk %d endpoint %s:%s",</span><br><span> trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr, endp->name, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, " Availability: %s%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_endp_avail(endp) ? "available" : "not in service", VTY_NEWLINE);</span><br><span> </span><br><span> if (llist_empty(&endp->conns)) {</span><br><span> vty_out(vty, " No active connections%s", VTY_NEWLINE);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-mgw/+/18898">change 18898</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-mgw/+/18898"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-mgw </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I18e90b10648a7e504371179ad144645fc82e1c27 </div>
<div style="display:none"> Gerrit-Change-Number: 18898 </div>
<div style="display:none"> Gerrit-PatchSet: 11 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>