diff --git a/CHANGES b/CHANGES index 69b0843286af6f37f686ad09482ac8b70b0a7db7..9d1c8a9a66e57333b1c5031c19184a4674fa6854 100644 --- a/CHANGES +++ b/CHANGES @@ -421,6 +421,8 @@ Miscellaneous configuration directory (/etc/asterisk by default) during reloads. * The parkeddynamic option has been added to features.conf to enable the creation of dynamic parkinglots. + * chan_dahdi now supports reporting alarms over AMI either by channel or span via + the reportalarms config option. ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2 ------------- diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index dacd234b373473a7d588c341dbf32047e1515d69..a9f322769c55496320dd4ee65a56005b4996f3d9 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -418,6 +418,10 @@ static int numbufs = 4; static int mwilevel = 512; static int dtmfcid_level = 256; +#define REPORT_CHANNEL_ALARMS 1 +#define REPORT_SPAN_ALARMS 2 +static int report_alarms = REPORT_CHANNEL_ALARMS; + #ifdef HAVE_PRI static int pridebugfd = -1; static char pridebugfilename[1024] = ""; @@ -963,6 +967,12 @@ struct dahdi_pvt { * \note Applies to SS7 and MFCR2 channels. */ unsigned int remotelyblocked:1; + /*! + * \brief TRUE if the channel alarms will be managed also as Span ones + * \note Applies to all channels + */ + unsigned int manages_span_alarms:1; + #if defined(HAVE_PRI) struct sig_pri_pri *pri; int prioffset; @@ -3022,6 +3032,18 @@ static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *da #endif } +static void handle_clear_alarms(struct dahdi_pvt *p) +{ + if (report_alarms & REPORT_CHANNEL_ALARMS) { + ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); + manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); + } + if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { + ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); + manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); + } +} + #ifdef HAVE_OPENR2 static int dahdi_r2_answer(struct dahdi_pvt *p) @@ -3110,8 +3132,7 @@ static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm) res = get_alarms(p); handle_alarms(p, res); } else { - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); + handle_clear_alarms(p); } ast_mutex_unlock(&p->lock); } @@ -5040,10 +5061,28 @@ static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt) } #endif /* defined(HAVE_PRI) */ +static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur) +{ + if (cur->next && cur->next->span == cur->span) { + return cur->next; + } else if (cur->prev && cur->prev->span == cur->span) { + return cur->prev; + } + + return NULL; +} + static void destroy_dahdi_pvt(struct dahdi_pvt *pvt) { struct dahdi_pvt *p = pvt; + if (p->manages_span_alarms) { + struct dahdi_pvt *next = find_next_iface_in_span(p); + if (next) { + next->manages_span_alarms = 1; + } + } + /* Remove channel from the list */ #if defined(HAVE_PRI) dahdi_unlink_pri_pvt(p); @@ -6953,11 +6992,21 @@ static void handle_alarms(struct dahdi_pvt *p, int alms) { const char *alarm_str = alarm2str(alms); - ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); - manager_event(EVENT_FLAG_SYSTEM, "Alarm", - "Alarm: %s\r\n" - "Channel: %d\r\n", - alarm_str, p->channel); + if (report_alarms & REPORT_CHANNEL_ALARMS) { + ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); + manager_event(EVENT_FLAG_SYSTEM, "Alarm", + "Alarm: %s\r\n" + "Channel: %d\r\n", + alarm_str, p->channel); + } + + if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { + ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); + manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", + "Alarm: %s\r\n" + "Span: %d\r\n", + alarm_str, p->span); + } } static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) @@ -7464,9 +7513,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) } #endif p->inalarm = 0; - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", - "Channel: %d\r\n", p->channel); + handle_clear_alarms(p); break; case DAHDI_EVENT_WINKFLASH: if (p->inalarm) break; @@ -9974,9 +10021,7 @@ static void *mwi_thread(void *data) break; case DAHDI_EVENT_NOALARM: mtd->pvt->inalarm = 0; - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", - "Channel: %d\r\n", mtd->pvt->channel); + handle_clear_alarms(mtd->pvt); break; case DAHDI_EVENT_ALARM: mtd->pvt->inalarm = 1; @@ -10390,9 +10435,7 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event) break; case DAHDI_EVENT_NOALARM: i->inalarm = 0; - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", - "Channel: %d\r\n", i->channel); + handle_clear_alarms(i); break; case DAHDI_EVENT_ALARM: i->inalarm = 1; @@ -16695,7 +16738,16 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct mwilevel = atoi(v->value); } else if (!strcasecmp(v->name, "dtmfcidlevel")) { dtmfcid_level = atoi(v->value); - } + } else if (!strcasecmp(v->name, "reportalarms")) { + if (!strcasecmp(v->value, "all")) + report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS; + if (!strcasecmp(v->value, "none")) + report_alarms = 0; + else if (!strcasecmp(v->value, "channels")) + report_alarms = REPORT_CHANNEL_ALARMS; + else if (!strcasecmp(v->value, "spans")) + report_alarms = REPORT_SPAN_ALARMS; + } } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); } @@ -16706,6 +16758,17 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct return -1; } } + + /* mark the first channels of each DAHDI span to watch for their span alarms */ + for (tmp = iflist, y=-1; tmp; tmp = tmp->next) { + if (!tmp->destroy && tmp->span != y) { + tmp->manages_span_alarms = 1; + y = tmp->span; + } else { + tmp->manages_span_alarms = 0; + } + } + /*< \todo why check for the pseudo in the per-channel section. * Any actual use for manual setup of the pseudo channel? */ if (!found_pseudo && reload != 1) { diff --git a/configs/chan_dahdi.conf.sample b/configs/chan_dahdi.conf.sample index 942375341024e2f97d52641cb541e7e7e97ab63f..fb0d06931c1ee68b11e72fed6805217aff258c9c 100644 --- a/configs/chan_dahdi.conf.sample +++ b/configs/chan_dahdi.conf.sample @@ -964,6 +964,14 @@ pickupgroup=1 ;context=default ;channel => 1 +; AMI alarm event reporting +;reportalarms=channels +;Possible values are: +;channels - report each channel alarms (current behavior, default for backward compatibility) +;spans - report an "SpanAlarm" event when the span of any configured channel is alarmed +;all - report channel and span alarms (aggregated behavior) +;none - do not report any alarms. + ; ---------------- Options for use with signalling=ss7 ----------------- ; None of them can be changed by a reload. ;