<p>Oron Peled would like Tzafrir Cohen to <strong>review</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11537">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">openr2(5/6): added cli command -- mfcr2 destroy link <index><br><br>Change-Id: I452d6a853bcd8c6e194455b19e5e017713e9c0fe<br>Signed-off-by: Oron Peled <oron.peled@xorcom.com><br>---<br>M channels/chan_dahdi.c<br>1 file changed, 185 insertions(+), 24 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/37/11537/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c</span><br><span>index 282ce56..35d9f96 100644</span><br><span>--- a/channels/chan_dahdi.c</span><br><span>+++ b/channels/chan_dahdi.c</span><br><span>@@ -762,6 +762,7 @@</span><br><span> openr2_context_t *protocol_context; /*!< OpenR2 context handle */</span><br><span> struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS]; /*!< Member channel pvt structs */</span><br><span> int numchans; /*!< Number of channels in this R2 block */</span><br><span style="color: hsl(120, 100%, 40%);">+ int live_chans; /*!< Number of unremoved channels in this R2 block */</span><br><span> int nodev; /*!< Link disconnected? */</span><br><span> struct dahdi_mfcr2_conf conf; /*!< Configuration used to setup this pseudo-link */</span><br><span> };</span><br><span>@@ -771,6 +772,8 @@</span><br><span> AST_LIST_ENTRY(r2link_entry) list;</span><br><span> };</span><br><span> static AST_LIST_HEAD_STATIC(r2links, r2link_entry);</span><br><span style="color: hsl(120, 100%, 40%);">+static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> /* how many r2links have been malloc'd */</span><br><span> static int r2links_count = 0;</span><br><span>@@ -3615,6 +3618,21 @@</span><br><span> }</span><br><span> </span><br><span> #ifdef HAVE_OPENR2</span><br><span style="color: hsl(120, 100%, 40%);">+static void mfcr2_queue_for_destruction(const struct dahdi_pvt *p)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct dahdi_mfcr2 *r2link = p->mfcr2;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct r2link_entry *cur;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_LOCK(&r2links);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (r2link == &cur->mfcr2) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "MFC/R2 channel %d queued for destruction\n", p->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_MOVE_CURRENT(&nodev_r2links, list);</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%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_TRAVERSE_SAFE_END;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_UNLOCK(&r2links);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static int dahdi_r2_answer(struct dahdi_pvt *p)</span><br><span> {</span><br><span>@@ -3700,6 +3718,9 @@</span><br><span> p->inalarm = alarm ? 1 : 0;</span><br><span> if (p->inalarm) {</span><br><span> res = get_alarms(p);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res == DAHDI_ALARM_NOTOPEN) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mfcr2_queue_for_destruction(p);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> handle_alarms(p, res);</span><br><span> } else {</span><br><span> handle_clear_alarms(p);</span><br><span>@@ -5556,6 +5577,50 @@</span><br><span> }</span><br><span> #endif /* defined(HAVE_SS7) */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_OPENR2)</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Unlink the channel interface from the MFC/R2 private pointer array.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 1.8</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param pvt chan_dahdi private interface structure to unlink.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Nothing</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void dahdi_unlink_mfcr2_pvt(struct dahdi_pvt *pvt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned idx;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_mfcr2 *mfcr2;</span><br><span style="color: hsl(120, 100%, 40%);">+ int should_destroy_link = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_lock(&pvt->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pvt->r2chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Disable MFC/R2 channel %d read\n", pvt->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ openr2_chan_disable_read(pvt->r2chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ mfcr2 = pvt->mfcr2;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mfcr2) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (idx = 0; idx < mfcr2->numchans; ++idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mfcr2->pvts[idx] == pvt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ mfcr2->pvts[idx] = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ mfcr2->live_chans--;</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%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mfcr2->live_chans) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "MFC/R2 link is now empty\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ should_destroy_link = 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%);">+ ast_mutex_unlock(&pvt->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (should_destroy_link) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "MFC/R2 link is now empty\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ mfcr2_queue_for_destruction(pvt);</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%);">+#endif /* defined(HAVE_OPENR2) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)</span><br><span> {</span><br><span> if (cur->next && cur->next->span == cur->span) {</span><br><span>@@ -5585,6 +5650,9 @@</span><br><span> #if defined(HAVE_SS7)</span><br><span> dahdi_unlink_ss7_pvt(p);</span><br><span> #endif /* defined(HAVE_SS7) */</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(HAVE_OPENR2)</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_unlink_mfcr2_pvt(p);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* defined(HAVE_SS7) */</span><br><span> switch (pvt->which_iflist) {</span><br><span> case DAHDI_IFLIST_NONE:</span><br><span> break;</span><br><span>@@ -11098,6 +11166,40 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_OPENR2</span><br><span style="color: hsl(120, 100%, 40%);">+static void dahdi_r2_destroy_nodev(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct r2link_entry *cur;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_LOCK(&nodev_r2links);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_TRAVERSE_SAFE_BEGIN(&nodev_r2links, cur, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_mfcr2 *r2 = &cur->mfcr2;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < r2->numchans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int channel;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *pvt = r2->pvts[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pvt) {</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%);">+ channel = pvt->channel;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "About to destroy B-channel %d.\n", channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_destroy_channel_range(channel, channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Destroying R2 link\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_REMOVE(&nodev_r2links, cur, list);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (r2->r2master != AST_PTHREADT_NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pthread_cancel(r2->r2master);</span><br><span style="color: hsl(120, 100%, 40%);">+ pthread_join(r2->r2master, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ r2->r2master = AST_PTHREADT_NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ openr2_context_delete(r2->protocol_context);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(cur);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_TRAVERSE_SAFE_END;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_UNLOCK(&nodev_r2links);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int setup_dahdi(int reload);</span><br><span> static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);</span><br><span> </span><br><span>@@ -11721,6 +11823,9 @@</span><br><span> }</span><br><span> ast_mutex_unlock(&iflock);</span><br><span> release_doomed_pris();</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_OPENR2</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_r2_destroy_nodev();</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> }</span><br><span> /* Never reached */</span><br><span> pthread_cleanup_pop(1);</span><br><span>@@ -11907,21 +12012,17 @@</span><br><span> static void dahdi_r2_destroy_links(void)</span><br><span> {</span><br><span> struct r2link_entry *cur;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Queue everything for removal */</span><br><span> AST_LIST_LOCK(&r2links);</span><br><span> AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct dahdi_mfcr2 *r2 = &cur->mfcr2;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(3, "Destroying R2 link\n");</span><br><span style="color: hsl(0, 100%, 40%);">- AST_LIST_REMOVE(&r2links, cur, list);</span><br><span style="color: hsl(0, 100%, 40%);">- if (r2->r2master != AST_PTHREADT_NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">- pthread_cancel(r2->r2master);</span><br><span style="color: hsl(0, 100%, 40%);">- pthread_join(r2->r2master, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- openr2_context_delete(r2->protocol_context);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(cur);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_MOVE_CURRENT(&nodev_r2links, list);</span><br><span> }</span><br><span> AST_LIST_TRAVERSE_SAFE_END;</span><br><span> AST_LIST_UNLOCK(&r2links);</span><br><span style="color: hsl(0, 100%, 40%);">- r2links_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Now destroy properly */</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_r2_destroy_nodev();</span><br><span> }</span><br><span> </span><br><span> /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */</span><br><span>@@ -12287,6 +12388,7 @@</span><br><span> destroy_dahdi_pvt(tmp);</span><br><span> return NULL;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+ r2_link->live_chans++;</span><br><span> tmp->mfcr2 = r2_link;</span><br><span> if (conf->mfcr2.call_files) {</span><br><span> openr2_chan_enable_call_files(tmp->r2chan);</span><br><span>@@ -13852,6 +13954,8 @@</span><br><span> static void *mfcr2_monitor(void *data)</span><br><span> {</span><br><span> struct dahdi_mfcr2 *mfcr2 = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *pvt;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* we should be using pthread_key_create</span><br><span> and allocate pollers dynamically.</span><br><span> I think do_monitor() could be leaking, since it</span><br><span>@@ -13868,8 +13972,11 @@</span><br><span> /* now that we're ready to get calls, unblock our side and</span><br><span> get current line state */</span><br><span> for (i = 0; i < mfcr2->numchans; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">- openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);</span><br><span style="color: hsl(0, 100%, 40%);">- openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ pvt = mfcr2->pvts[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pvt)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ openr2_chan_set_idle(pvt->r2chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ openr2_chan_handle_cas(pvt->r2chan);</span><br><span> }</span><br><span> while (1) {</span><br><span> /* we trust here that the mfcr2 channel list will not ever change once</span><br><span>@@ -13878,20 +13985,23 @@</span><br><span> for (i = 0; i < mfcr2->numchans; i++) {</span><br><span> pollers[i].revents = 0;</span><br><span> pollers[i].events = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- if (mfcr2->pvts[i]->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pvt = mfcr2->pvts[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pvt)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pvt->owner) {</span><br><span> continue;</span><br><span> }</span><br><span> if (mfcr2->nodev) {</span><br><span> continue;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mfcr2->pvts[i]->r2chan) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pvt->r2chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Wow, no r2chan on channel %d\n", pvt->channel);</span><br><span> quit_loop = 1;</span><br><span> break;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ openr2_chan_enable_read(pvt->r2chan);</span><br><span> pollers[i].events = POLLIN | POLLPRI;</span><br><span style="color: hsl(0, 100%, 40%);">- pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;</span><br><span style="color: hsl(120, 100%, 40%);">+ pollers[i].fd = pvt->subs[SUB_REAL].dfd;</span><br><span> pollsize++;</span><br><span> }</span><br><span> if (quit_loop) {</span><br><span>@@ -13918,8 +14028,11 @@</span><br><span> /* do we want to allow to cancel while processing events? */</span><br><span> pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);</span><br><span> for (i = 0; i < mfcr2->numchans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pvt = mfcr2->pvts[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pvt)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span> if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {</span><br><span style="color: hsl(0, 100%, 40%);">- openr2_chan_process_event(mfcr2->pvts[i]->r2chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ openr2_chan_process_event(pvt->r2chan);</span><br><span> }</span><br><span> }</span><br><span> pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);</span><br><span>@@ -15223,6 +15336,51 @@</span><br><span> return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static char *handle_mfcr2_destroy_link(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res;</span><br><span style="color: hsl(120, 100%, 40%);">+ int wanted_link_index;</span><br><span style="color: hsl(120, 100%, 40%);">+ int found_link = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct r2link_entry *cur = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "mfcr2 destroy link";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+ "Usage: mfcr2 destroy link <index-number>\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Destorys D-channel of link and its B-channels.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc < 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ res = sscanf(a->argv[3], "%30d", &wanted_link_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((res != 1) || wanted_link_index < 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_LOCK(&r2links);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (wanted_link_index == mfcr2->index) {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_MOVE_CURRENT(&nodev_r2links, list);</span><br><span style="color: hsl(120, 100%, 40%);">+ r2links_count--;</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%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_TRAVERSE_SAFE_END;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_UNLOCK(&r2links);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (! found_link) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "No link found with index %d.\n", wanted_link_index);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ast_cli_entry dahdi_mfcr2_cli[] = {</span><br><span> AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),</span><br><span> AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),</span><br><span>@@ -15232,6 +15390,7 @@</span><br><span> AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),</span><br><span> AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),</span><br><span> AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(handle_mfcr2_destroy_link, "Destroy given MFC/R2 link"),</span><br><span> };</span><br><span> </span><br><span> #endif /* HAVE_OPENR2 */</span><br><span>@@ -19567,13 +19726,15 @@</span><br><span> AST_LIST_LOCK(&r2links);</span><br><span> AST_LIST_TRAVERSE(&r2links, cur, list) {</span><br><span> struct dahdi_mfcr2 *r2 = &cur->mfcr2;</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (r2->r2master == AST_PTHREADT_NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ x++;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- x++;</span><br><span> }</span><br><span> AST_LIST_UNLOCK(&r2links);</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11537">change 11537</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.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.asterisk.org/c/asterisk/+/11537"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: I452d6a853bcd8c6e194455b19e5e017713e9c0fe </div>
<div style="display:none"> Gerrit-Change-Number: 11537 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Oron Peled <oron.peled@xorcom.com> </div>
<div style="display:none"> Gerrit-Reviewer: Tzafrir Cohen <tzafrir.cohen@xorcom.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>