--- /dev/null
+#!/bin/sh
+#
+# Example init.d script with LSB support.
+#
+# Please read this init.d carefully and modify the sections to
+# adjust it to the program you want to run.
+#
+# Copyright (c) 2007, 2009 Javier Fernandez-Sanguino <jfs@debian.org>
+#
+# This is free software; you may redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2,
+# or (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License with
+# the Debian operating system, in /usr/share/common-licenses/GPL; if
+# not, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA 02111-1307 USA
+#
+### BEGIN INIT INFO
+# Provides: openvswitch-wdt
+# Required-Start: $network $local_fs
+# Required-Stop:
+# Should-Start: $named $syslog openvswitch-switch
+# Should-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: OpenVSwitch switch watchdog
+### END INIT INFO
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
+DAEMON=/usr/sbin/ovs-wdt
+NAME=openvswitch-wdt
+DESC="OpenVSwitch switch watchdog"
+
+PIDFILE=/var/run/$NAME.pid
+
+test -x $DAEMON || exit 0
+
+. /lib/lsb/init-functions
+
+# Default options, these can be overriden by the information
+# at /etc/default/$NAME
+DAEMON_OPTS="" # Additional options given to the daemon
+
+DODTIME=10 # Time to wait for the daemon to die, in seconds
+ # If this value is set too low you might not
+ # let some daemons to die gracefully and
+ # 'restart' will not work
+
+# Include defaults if available
+if [ -f /etc/default/$NAME ] ; then
+ . /etc/default/$NAME
+fi
+
+set -e
+
+running_pid() {
+# Check if a given process pid's cmdline matches a given name
+ pid=$1
+ name=$2
+ [ -z "$pid" ] && return 1
+ [ ! -d /proc/$pid ] && return 1
+ return 0
+}
+
+running() {
+# Check if the process is running looking at /proc
+# (works for all users)
+
+ # No pidfile, probably no daemon present
+ [ ! -f "$PIDFILE" ] && return 1
+ pid=`cat $PIDFILE`
+ running_pid $pid $DAEMON || return 1
+ return 0
+}
+
+start_daemon() {
+# Start the process using the wrapper
+ if test $WDT_TIMEOUT != 0; then
+ start-stop-daemon --start --quiet -m --background --pidfile $PIDFILE \
+ --exec $DAEMON -- --timeout=$WDT_TIMEOUT --interval=$WDT_INTERVAL $DAEMON_OPTS
+ fi
+
+ # Wait up to 3 seconds for the daemon to start.
+ for i in 1 2 3; do
+ if running; then
+ break
+ fi
+ sleep 1
+ done
+
+ echo $OOPS_REBOOT_TIME > /proc/sys/kernel/panic
+ echo 1 > /proc/sys/kernel/panic_on_oops
+}
+
+stop_daemon() {
+ start-stop-daemon -o --stop --pidfile $PIDFILE
+ rm $PIDFILE
+}
+
+case "$1" in
+ start)
+ log_daemon_msg "Starting $DESC " "$NAME"
+ # Check if it's running first
+ if running ; then
+ log_progress_msg "apparently already running"
+ log_end_msg 0
+ exit 0
+ fi
+ if start_daemon && running ; then
+ # It's ok, the daemon started and is running
+ log_end_msg 0
+ else
+ # Either we could not start it or it is not running
+ # after we did
+ # NOTE: Some daemons might die some time after they start,
+ # this code does not try to detect this and might give
+ # a false positive (use 'status' for that)
+ log_end_msg 1
+ fi
+ ;;
+ stop)
+ log_daemon_msg "Stopping $DESC" "$NAME"
+ if running ; then
+ # Only stop the daemon if we see it running
+ stop_daemon
+ log_end_msg $?
+ else
+ # If it's not running don't do anything
+ log_progress_msg "apparently not running"
+ log_end_msg 0
+ exit 0
+ fi
+ ;;
+ restart|force-reload)
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ if running ; then
+ stop_daemon
+ # Wait some sensible amount, some daemons need this
+ [ -n "$DIETIME" ] && sleep $DIETIME
+ fi
+ start_daemon
+ running
+ log_end_msg $?
+ ;;
+ status)
+ log_daemon_msg "Checking status of $DESC" "$NAME"
+ if running ; then
+ log_progress_msg "running"
+ log_end_msg 0
+ else
+ log_progress_msg "apparently not running"
+ log_end_msg 1
+ exit 1
+ fi
+ ;;
+ # Use this if the daemon cannot reload
+ reload)
+ log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon"
+ log_warning_msg "cannot re-read the config file (use restart)."
+ ;;
+ *)
+ N=/etc/init.d/$NAME
+ echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
--- /dev/null
+/* Copyright (c) 2008, 2009 Nicira Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, Nicira Networks gives permission
+ * to link the code of its release of vswitchd with the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the same
+ * license as the "OpenSSL" library), and distribute the linked
+ * executables. You must obey the GNU General Public License in all
+ * respects for all of the code used other than "OpenSSL". If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+
+/* Default values for the interval and timer. In seconds. */
+#define DEFAULT_INTERVAL 1
+#define DEFAULT_TIMEOUT 30
+
+int fd = -1;
+
+/* The WDT is automatically enabled when /dev/watchdog is opened. If we
+ * do not send the magic value to the device first before exiting, the
+ * system will reboot. This function allows the program to exit without
+ * causing a reboot.
+ */
+static void
+cleanup(void)
+{
+ if (fd == -1) {
+ return;
+ }
+
+ /* Writing the magic value "V" to the device is an indication that
+ * the device is about to be closed. This causes the watchdog to be
+ * disabled after the call to close.
+ */
+ if (write(fd, "V", 1) != 1) {
+ fprintf(stderr, "Couldn't write magic val: %d\n", errno);
+ return;
+ }
+ close(fd);
+ fd = -1;
+}
+
+
+/* If we receive a SIGINT, cleanup first, which will disable the
+ * watchdog timer.
+ */
+static void
+sighandler(int signum)
+{
+ cleanup();
+ signal(signum, SIG_DFL);
+ raise(signum);
+}
+
+static void
+setup_signal(void)
+{
+ struct sigaction action;
+
+ action.sa_handler = sighandler;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = 0;
+
+ if (sigaction(SIGINT, &action, NULL) != 0) {
+ fprintf(stderr, "Problem setting up SIGINT handler...\n");
+ }
+ if (sigaction(SIGTERM, &action, NULL) != 0) {
+ fprintf(stderr, "Problem setting up SIGTERM handler...\n");
+ }
+}
+
+
+/* Print information on the WDT hardware */
+static void
+print_wdt_info(void)
+{
+ struct watchdog_info ident;
+
+ if (ioctl(fd, WDIOC_GETSUPPORT, &ident) == -1) {
+ fprintf(stderr, "Couldn't get version: %d\n", errno);
+ cleanup();
+ exit(-1);
+ }
+ printf("identity: %s, ver: %d, opt: %#x\n", ident.identity,
+ ident.firmware_version, ident.options);
+}
+
+
+static void
+print_help(char *progname)
+{
+ printf("%s: Watchdog timer utility\n", progname);
+ printf("usage: %s [OPTIONS]\n\n", progname);
+ printf("Options:\n");
+ printf(" -t, --timeout=SECS expiration time of WDT (default: %d)\n",
+ DEFAULT_TIMEOUT);
+ printf(" -i, --interval=SECS interval to send keep-alives (default: %d)\n",
+ DEFAULT_INTERVAL);
+ printf(" -d, --disable disable the WDT and exit\n");
+ printf(" -h, --help display this help message\n");
+ printf(" -v, --verbose enable verbose printing\n");
+ printf(" -V, --version display version information of WDT and exit\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+ int arg;
+ int optc;
+ int verbose = 0;
+ int interval = DEFAULT_INTERVAL;
+ int timeout = DEFAULT_TIMEOUT;
+ static struct option const longopts[] =
+ {
+ {"timeout", required_argument, NULL, 't'},
+ {"interval", required_argument, NULL, 'i'},
+ {"disable", no_argument, NULL, 'd'},
+ {"help", no_argument, NULL, 'h'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
+ {0, 0, 0, 0}
+ };
+
+ setup_signal();
+
+ fd = open("/dev/watchdog", O_RDWR);
+ if (fd == -1) {
+ fprintf(stderr, "Couldn't open watchdog device: %s\n", strerror(errno));
+ exit(-1);
+ }
+
+ while ((optc = getopt_long(argc, argv, "t:i:dh?vV", longopts, NULL)) != -1) {
+ switch (optc) {
+ case 't':
+ timeout = strtol(optarg, NULL, 10);
+ if (!timeout) {
+ fprintf(stderr, "Invalid timeout: %s\n", optarg);
+ goto error;
+ }
+ break;
+
+ case 'i':
+ interval = strtol(optarg, NULL, 10);
+ if (!interval) {
+ fprintf(stderr, "Invalid interval: %s\n", optarg);
+ goto error;
+ }
+ break;
+
+ case 'd':
+ arg = WDIOS_DISABLECARD;
+ if (ioctl(fd, WDIOC_SETOPTIONS, &arg) == -1) {
+ fprintf(stderr, "Couldn't disable: %d\n", errno);
+ goto error;
+ }
+ cleanup();
+ exit(0);
+ break;
+
+ case 'h':
+ print_help(argv[0]);
+ cleanup();
+ exit(0);
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'V':
+ print_wdt_info();
+ cleanup();
+ exit(0);
+ break;
+
+ default:
+ print_help(argv[0]);
+ goto error;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Sanity-check the arguments */
+ if (argc != 0) {
+ fprintf(stderr, "Illegal argument: %s\n", argv[0]);
+ goto error;
+ }
+
+ if (verbose) {
+ print_wdt_info();
+ printf("timeout: %d, interval: %d\n", timeout, interval);
+ }
+
+ /* Prevent the interval being greater than the timeout, since it
+ * will always cause a reboot.
+ */
+ if (interval > timeout) {
+ fprintf(stderr, "Interval greater than timeout: %d > %d\n",
+ interval, timeout);
+ goto error;
+ }
+
+ /* Always set the timeout */
+ if (ioctl(fd, WDIOC_SETTIMEOUT, &timeout) == -1) {
+ fprintf(stderr, "Couldn't set timeout: %d\n", errno);
+ goto error;
+ }
+
+ /* Loop and send a keep-alive every "interval" seconds */
+ while (1) {
+ if (verbose) {
+ if (ioctl(fd, WDIOC_GETTIMELEFT, &arg) == -1) {
+ fprintf(stderr, "Couldn't get time left: %d\n", errno);
+ goto error;
+ }
+ printf("Sending keep alive, time remaining: %d\n", arg);
+ }
+
+ /* Send a keep-alive. The argument is ignored */
+ if (ioctl(fd, WDIOC_KEEPALIVE, &arg) == -1) {
+ fprintf(stderr, "Couldn't keepalive: %d\n", errno);
+ goto error;
+ }
+
+ sleep(interval);
+ }
+
+ /* Never directly reached... */
+error:
+ cleanup();
+ exit(-1);
+}