[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