[clue] [tech] How to get explicit notification from a network device driver?
Will
will.sterling at gmail.com
Tue Apr 24 14:39:07 MDT 2012
You can use named pipes and a daemon that only acts when output from a
given Syslog facility arrives. It strikes a balance between the effort
required to modify a driver and keep it up to date and spending extra
resources on a daemon that does regular polling.
I've done similar for a client that wanted instantaneous e-mails when a
given authorization error was sent to syslog.
These are the instructions I gave for HP-UX but they should work in Linux
with some small changes.
1. Create the named pipe "mkfifo /var/adm/syslog/syslog.pipe
2. Put to following script in /usr/local/bin/syslogMailer or another
location, modify the mail recipient and Pattern.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#!/bin/sh
# syslogMailer: a script to read stdin and turn each line into an alert
# email typically this is used to read a named-pipe written to by syslog
#
# example usage: syslogMailer < /etc/syslog.pipes/criticalMessages
#
alertRecipient="fireman at example.com" # the mail recipient for alerts
# process each line of input and produce an error message
while :
do
while read line
do
# Send only messages I care about.
echo ${line} | grep "SOME_PATTERN" > /dev/null 2>&1
if test $? -eq 0
# send the alert
echo "${line}" | mailx -s "PATTERN alert on syslog"
${alertRecipient}
fi
done
done
++++++++++++++++++++++++++++++++++++++++++++++++++++++
3. Put the following in /sbin/init.d/syslogMailer
+++++++++++++++++++++++++++++++++++++++++++++++++++
#!/sbin/sh
#
# Start the syslogMailer script as a Daemon.
#
PATH=/sbin:/usr/sbin:/usr/bin:/usr/local/bin
export PATH
SM_PATH=/usr/local/bin/syslogMailer
NAMED_PIPE=/var/adm/syslog/syslog.pipe
rval=0
GetNamedProcIds()
{
ps -e | awk -v mypid=$$ -v pname=$1 \
'$NF==pname { \
if ($1 != mypid) \
print $1 \
}'
}
case $1 in
start_msg)
echo "Starting syslogMailer"
;;
'start')
pids=`GetNamedProcIds "syslogMailer"`
if [ "X$pids" != "X" ]; then
kill $pids 1>/dev/null 2>&1
fi
$SM_PATH < $NAMED_PIPE > /dev/null 2>&1
x=$?
if [ $x -eq 0 ]
then
echo 'syslogMailer active'
else
echo "Warning: syslogMailer returned exit code: $x"
rval=1
fi
;;
'stop_msg')
echo "Stop syslogMailer daemon"
;;
'stop')
#
# Determine PIDs of process(es) to stop
#
pids=`GetNamedProcIds "syslogMailer"`
kill $pids 1>/dev/null 2>&1
echo "syslogMailer stopped"
#
# Set return value to be zero.
#
rval=0;
;;
*)
echo "usage: $0 {start}"
rval=1
;;
esac
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4. create links so the init.d script is called during startup and shutdown.
"ln -s /sbin/init.d/syslogMailer /sbin/rc2.d/S999syslogMailer;ln -s
/sbin/init.d/syslogMailer /sbin/rc1.d/K999syslogMailer"
5. Edit /etc/syslog.conf and add the following line:
facility.level /var/adm/syslog/syslog.pipe
6. Restart syslog "/sbin/init.d/syslogd stop;/sbin/init.d/syslogd start"
7. Start syslogMailer "/sbin/init.d/syslogMailer start"
8. Test by generating alert to syslog.
On Mon, Apr 23, 2012 at 2:19 PM, Jim Ockers <ockers at ockers.net> wrote:
> **
> Hi everyone,
>
> The state of the art in determining ethernet link state, and taking any
> action based on changes, seems to be to run a daemon that repeatedly polls
> the network interface and using an ioctl (SIOCGMIIPHY, SIOCETHTOOL) finds
> out if there is an ethernet link or not.
>
> It seems like it would be more deterministic, and less resource intensive,
> to just have the network card device driver DO something (or cause
> something to be done) when the link state changes. For an embedded device
> with limited CPU I think while(1) polling is sub-optimal. It also seems
> like it should not be too hard to get the device driver to do something
> useful in addition to its printk() message about the changed link state.
>
> How could I do this? I think system() is a bad idea because I'm not sure a
> device driver should be starting other processes that may block or
> something. Also system() requires unistd.h and the kernel compile/build
> system doesn't seem to give drivers access to that sort of normal libc
> functions. Anyway I welcome any ideas.
>
> For example the driver doesn't compile with the 2 lines I added (marked
> with +), and also unistd.h is not found even though I #included it:
>
> if (!port->link) {
> netif_carrier_off(dev);
> printk(KERN_INFO "%s: link down\n", dev->name);
> + printk(KERN_INFO "%s: link down, running /usr/bin/wanlinkdown\n",
> dev->name);
> + system("/usr/bin/wanlinkdown");
> return;
> }
>
> I'm not heart-broken that this doesn't work because I didn't like this
> approach to begin with, but I'm still not sure exactly what would be the
> best way to get a notification without polling. So far the only
> "notification" is the KERN_INFO message that gets printed to the dmesg log
> and also whatever is specified in syslog.conf (kern.info goes to *, which
> includes the console). In addition to the notification I want it to run a
> program or something so I get explicit real-time notification of link state
> changes without constantly polling.
>
> Thanks,
> Jim
>
> --
> Jim Ockers, P.E., P.Eng. (ockers at ockers.net)
> Contact info: http://www.ockers.net/
>
>
> _______________________________________________
> clue mailing list: clue at cluedenver.org
> For information, account preferences, or to unsubscribe see:
> http://cluedenver.org/mailman/listinfo/clue
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://cluedenver.org/pipermail/clue/attachments/20120424/b25d4297/attachment.html
More information about the clue
mailing list