<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-mgw/+/18898">View Change</a></p><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>withi 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, 279 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/98/18898/1</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..5607c31 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,10 @@</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> /* 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>@@ -213,7 +217,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 +368,251 @@</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(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%);">+                 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(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%);">+    static const uint8_t rates[] = { 64, 32, 16, 16, 8 };</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%);">+                 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(rates); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (res == 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(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%);">+                   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(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%);">+ /* See also comment in gen_e1_epname() */</span><br><span style="color: hsl(120, 100%, 40%);">+     static const uint8_t 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 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 style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sizeof(rates) == sizeof(offsets));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < sizeof(rates); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if ((rates[i] == rate) && (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 subsolt number (array index) and the</span><br><span style="color: hsl(120, 100%, 40%);">+   * rate in the form: i:r where i is the subsolt 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%);">+   static 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%);">+</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<15;i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Detect table 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", 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 occurr</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 obsticels 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..52fbf6e 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:availability", "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:availability", "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:availability", "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: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>