[svn-commits] rmudgett: branch group/CCSS r245188 - /team/group/CCSS/channels/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Fri Feb 5 18:54:34 CST 2010
Author: rmudgett
Date: Fri Feb 5 18:54:30 2010
New Revision: 245188
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=245188
Log:
Add ISDN span congestion device state so CCSS can monitor when trunk congestion goes away.
* Also have place holder code that partially implements a user
configurable busy threshold span device state. This is indented to help
an administrator to determine if more ISDN capacity is needed.
Modified:
team/group/CCSS/channels/chan_dahdi.c
team/group/CCSS/channels/sig_pri.c
team/group/CCSS/channels/sig_pri.h
Modified: team/group/CCSS/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/channels/chan_dahdi.c?view=diff&rev=245188&r1=245187&r2=245188
==============================================================================
--- team/group/CCSS/channels/chan_dahdi.c (original)
+++ team/group/CCSS/channels/chan_dahdi.c Fri Feb 5 18:54:30 2010
@@ -1448,6 +1448,7 @@
static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
+static int dahdi_devicestate(void *data);
static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
static const struct ast_channel_tech dahdi_tech = {
@@ -1471,6 +1472,7 @@
.queryoption = dahdi_queryoption,
.func_channel_read = dahdi_func_read,
.func_channel_write = dahdi_func_write,
+ .devicestate = dahdi_devicestate,
.cc_callback = dahdi_cc_callback,
};
@@ -2866,6 +2868,72 @@
/*!
* \internal
+ * \brief Reevaluate the PRI span device state.
+ * \since 1.8
+ *
+ * \param pri Asterisk D channel control structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes the pri->lock is already obtained.
+ */
+static void dahdi_pri_update_span_devstate(struct sig_pri_pri *pri)
+{
+ unsigned idx;
+ unsigned num_b_chans; /* Number of B channels provisioned on the span. */
+ unsigned in_use; /* Number of B channels in use on the span. */
+ unsigned in_alarm; /* TRUE if the span is in alarm condition. */
+ enum ast_device_state new_state;
+
+ /* Count the number of B channels and the number of B channels in use. */
+ num_b_chans = 0;
+ in_use = 0;
+ in_alarm = 1;
+ for (idx = pri->numchans; idx--;) {
+ if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
+ /* This is a B channel interface. */
+ ++num_b_chans;
+ if (pri->pvts[idx]->owner) {
+ ++in_use;
+ }
+ if (!pri->pvts[idx]->inalarm) {
+ /* There is a channel that is not in alarm. */
+ in_alarm = 0;
+ }
+ }
+ }
+
+ /* Update the span congestion device state and report any change. */
+ if (in_alarm) {
+ new_state = AST_DEVICE_UNAVAILABLE;
+ } else {
+ new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
+ }
+ if (pri->congestion_devstate != new_state) {
+ pri->congestion_devstate = new_state;
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
+ }
+#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
+ /* Update the span threshold device state and report any change. */
+ if (in_alarm) {
+ new_state = AST_DEVICE_UNAVAILABLE;
+ } else if (!in_use) {
+ new_state = AST_DEVICE_NOT_INUSE;
+ } else if (!pri->user_busy_threshold) {
+ new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
+ } else {
+ new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
+ : AST_DEVICE_BUSY;
+ }
+ if (pri->threshold_devstate != new_state) {
+ pri->threshold_devstate = new_state;
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
+ }
+#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
+}
+
+/*!
+ * \internal
* \brief Reference this module.
* \since 1.8
*
@@ -2908,6 +2976,7 @@
.new_nobch_intf = dahdi_new_pri_nobch_channel,
.get_orig_dialstring = my_get_orig_dialstring,
.make_cc_dialstring = my_pri_make_cc_dialstring,
+ .update_span_devstate = dahdi_pri_update_span_devstate,
.module_ref = my_module_ref,
.module_unref = my_module_unref,
};
@@ -12486,6 +12555,58 @@
}
/*!
+ * \internal
+ * \brief Determine the device state for a given DAHDI device if we can.
+ * \since 1.8
+ *
+ * \param data DAHDI device name after "DAHDI/".
+ *
+ * \retval device_state enum ast_device_state value.
+ * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
+ */
+static int dahdi_devicestate(void *data)
+{
+ char *device;
+ unsigned span;
+ int res;
+
+ device = data;
+
+ if (*device != 'I') {
+ /* The request is not for an ISDN span device. */
+ return AST_DEVICE_UNKNOWN;
+ }
+ res = sscanf(device, "I%30u", &span);
+ if (res != 1 || !span || NUM_SPANS < span) {
+ /* Bad format for ISDN span device name. */
+ return AST_DEVICE_UNKNOWN;
+ }
+ device = strchr(device, '/');
+ if (!device) {
+ /* Bad format for ISDN span device name. */
+ return AST_DEVICE_UNKNOWN;
+ }
+
+ /*
+ * Since there are currently no other span devstate's defined,
+ * it must be congestion.
+ */
+#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
+ ++device;
+ if (!strcmp(device, "congestion"))
+#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
+ {
+ return pris[span - 1].pri.congestion_devstate;
+ }
+#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
+ else if (!strcmp(device, "threshold")) {
+ return pris[span - 1].pri.threshold_devstate;
+ }
+ return AST_DEVICE_UNKNOWN;
+#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
+}
+
+/*!
* \brief Callback made when dial failed to get a channel out of dahdi_request().
* \since 1.8
*
@@ -12532,26 +12653,32 @@
case AST_CC_MONITOR_GENERIC:
#if defined(HAVE_PRI)
if (dahdi_sig_pri_lib_handles(p->sig)) {
- char address[AST_CHANNEL_NAME];
-
- sig_pri_extract_called_num_subaddr(p->sig_pvt, dest, address, sizeof(address));
- device_name = create_channel_name(p, 1, address);
- } else {
+ /*
+ * ISDN is in a trunk busy condition so we need to monitor
+ * the span congestion device state.
+ */
+ snprintf(full_device_name, sizeof(full_device_name),
+ "DAHDI/I%d/congestion", p->pri->span);
+ } else
+#endif /* defined(HAVE_PRI) */
+ {
+#if defined(HAVE_PRI)
device_name = create_channel_name(p, 1, "");
- }
#else
- device_name = create_channel_name(p);
+ device_name = create_channel_name(p);
#endif /* defined(HAVE_PRI) */
- snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", ast_str_buffer(device_name));
- ast_free(device_name);
- /*
- * The portion after the '-' in the channel name is either a random
- * number, a sequence number, or a subchannel number. None are
- * necessary so strip them off.
- */
- dash = strrchr(full_device_name, '-');
- if (dash) {
- *dash = '\0';
+ snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
+ device_name ? ast_str_buffer(device_name) : "");
+ ast_free(device_name);
+ /*
+ * The portion after the '-' in the channel name is either a random
+ * number, a sequence number, or a subchannel number. None are
+ * necessary so strip them off.
+ */
+ dash = strrchr(full_device_name, '-');
+ if (dash) {
+ *dash = '\0';
+ }
}
snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
@@ -12559,7 +12686,7 @@
* Analog can only do generic monitoring.
* ISDN is in a trunk busy condition and any "device" is going
* to be busy until a B channel becomes available. The generic
- * monitor can be made to do this task.
+ * monitor can do this task.
*/
monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
callback(inbound,
Modified: team/group/CCSS/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/channels/sig_pri.c?view=diff&rev=245188&r1=245187&r2=245188
==============================================================================
--- team/group/CCSS/channels/sig_pri.c (original)
+++ team/group/CCSS/channels/sig_pri.c Fri Feb 5 18:54:30 2010
@@ -161,6 +161,24 @@
}
}
#endif /* defined(HAVE_PRI_CCSS) */
+
+/*!
+ * \internal
+ * \brief Reevaluate the PRI span device state.
+ * \since 1.8
+ *
+ * \param pri Asterisk D channel control structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes the pri->lock is already obtained.
+ */
+static void sig_pri_span_devstate_changed(struct sig_pri_pri *pri)
+{
+ if (pri->calls->update_span_devstate) {
+ pri->calls->update_span_devstate(pri);
+ }
+}
/*!
* \internal
@@ -779,6 +797,12 @@
c->transfercapability = transfercapability;
pbx_builtin_setvar_helper(c, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
sig_pri_set_digital(p, 1);
+ }
+ if (p->pri && !pri_grab(p, p->pri)) {
+ sig_pri_span_devstate_changed(p->pri);
+ pri_rel(p->pri);
+ } else {
+ ast_log(LOG_WARNING, "Failed to grab PRI!\n");
}
return c;
@@ -2496,6 +2520,7 @@
f.subclass.integer = AST_CONTROL_HOLD;
ast_queue_frame(owner, &f);
+ sig_pri_span_devstate_changed(pri);
retval = 0;
}
@@ -2569,6 +2594,7 @@
pri_queue_frame(pri->pvts[chanpos], &f, pri);
}
sig_pri_unlock_private(pri->pvts[chanpos]);
+ sig_pri_span_devstate_changed(pri);
pri_retrieve_ack(pri->pri, ev->retrieve.call,
PVT_TO_CHANNEL(pri->pvts[chanpos]));
}
@@ -2797,10 +2823,12 @@
}
pri->resetting = 0;
/* Take the channels from inalarm condition */
- for (i = 0; i < pri->numchans; i++)
+ for (i = 0; i < pri->numchans; i++) {
if (pri->pvts[i]) {
pri->pvts[i]->inalarm = 0;
}
+ }
+ sig_pri_span_devstate_changed(pri);
break;
case PRI_EVENT_DCHAN_DOWN:
pri_find_dchan(pri);
@@ -2831,6 +2859,7 @@
p->inalarm = 1;
}
}
+ sig_pri_span_devstate_changed(pri);
}
break;
case PRI_EVENT_RESTART:
@@ -4025,6 +4054,7 @@
/* Make sure we have a call (or REALLY have a call in the case of a PRI) */
if (!pri_grab(p, p->pri)) {
+ sig_pri_span_devstate_changed(p->pri);
if (p->alreadyhungup) {
ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
Modified: team/group/CCSS/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/channels/sig_pri.h?view=diff&rev=245188&r1=245187&r2=245188
==============================================================================
--- team/group/CCSS/channels/sig_pri.h (original)
+++ team/group/CCSS/channels/sig_pri.h Fri Feb 5 18:54:30 2010
@@ -116,6 +116,7 @@
int (* const new_nobch_intf)(struct sig_pri_pri *pri);
const char *(* const get_orig_dialstring)(void *pvt);
void (* const make_cc_dialstring)(void *pvt, char *buf, size_t buf_size);
+ void (* const update_span_devstate)(struct sig_pri_pri *pri);
/*! Reference the parent module. */
void (*module_ref)(void);
@@ -295,6 +296,37 @@
ast_mutex_t lock; /*!< libpri access Mutex */
time_t lastreset; /*!< time when unused channels were last reset */
struct sig_pri_callback *calls;
+ /*!
+ * \brief Congestion device state of the span.
+ * \details
+ * AST_DEVICE_NOT_INUSE - Span does not have all B channels in use.
+ * AST_DEVICE_BUSY - All B channels are in use.
+ * AST_DEVICE_UNAVAILABLE - Span is in alarm.
+ * \note
+ * Device name: DAHDI/I<span>/congestion
+ */
+ int congestion_devstate;
+#if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
+ /*! \todo An ISDN span threshold device state could be useful in determining how often a span utilization goes over a configurable threshold. */
+ /*!
+ * \brief User threshold device state of the span.
+ * \details
+ * AST_DEVICE_NOT_INUSE - There are no B channels in use.
+ * AST_DEVICE_INUSE - The number of B channels in use is less than
+ * the configured threshold but not zero.
+ * AST_DEVICE_BUSY - The number of B channels in use meets or exceeds
+ * the configured threshold.
+ * AST_DEVICE_UNAVAILABLE - Span is in alarm.
+ * \note
+ * Device name: DAHDI/I<span>/threshold
+ */
+ int threshold_devstate;
+ /*!
+ * \brief Number of B channels in use to consider the span in a busy state.
+ * \note Setting the threshold to zero is interpreted as all B channels.
+ */
+ int user_busy_threshold;
+#endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
};
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size);
More information about the svn-commits
mailing list