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