Re: [patch] netconsole-2.4.10-B1

From: Andreas Dilger (adilger@turbolabs.com)
Date: Fri Sep 28 2001 - 02:08:19 EST


On Sep 27, 2001 08:38 +0200, Ingo Molnar wrote:
> the patch also includes Andrew Morton's suggestion to add the
> HAVE_POLL_CONTROLLER define for easier network-driver integration. The
> eepro100.c changes now use this define.
>
> the new utilities-tarball is at:
>
> http://redhat.com/~mingo/netconsole-patches/netconsole-client-20010927.tar.gz

A few minor changes to the code, after testing it a bit locally (note that I
am using kernel patch C1):

First, a patch to change the MAC address kernel parameter to be in the
standard XX:XX:XX:XX:XX:XX form, instead of separate bytes. It also
fixes the output of the IP addresses to be unsigned ints. Isn't there
a function in the kernel to format IP addresses for output already?

Next, a patch to netconsole-server to use the target_mac parameter
instead of the target_eth_byteX parameters. I thought about keeping
these around for compatibility, but since this is a relatively new
tool there is no point in keeping the extra baggage.

TODO: figure out what "offset" is really supposed to be useful for. Maybe
      it should be aligned properly, and we add the message priority into
      one of the free bytes?

Finally, a patch to netconsole-client.c which does a few things:
- remove "offset" from output, it appears meaningless and screws formatting.
- allow the client to receive messages from multiple servers, unless a
  single server is specified.
- log to syslog (this is a bit complex because of the desire to write full
  lines into the syslog as opposed to chunks of the size sent by printk().
- (minor) change parameters to use "--" long option names in preparation
  for using getopt-long to do CLI parsing.
- (minor) don't require the --port option (use 6666 as default)
- (minor) don't require the --server option (accept all messages by default)

TODO: don't require the --client option (get ipaddress from interface and/or
      listen on all interfaces by default)
TODO: add getopt_long parsing of options to avoid ordered option requirement
TODO: make syslog and stdout logging optional (need one or the other obviously)
TODO: print server IP/hostname in syslog/stdout output in case we are getting
      messages from multiple servers
TODO: figure out why LOG_KERN does not show up in kernel log, while klogd does
TODO: add timeout for messages in syslog output buffer.
TODO: allow client/server to be specified by both hostname/IP
TODO: allow different client/server port numbers? Do we care?

As an added bonus, a patch for 8139too.c which adds poll support (Jeff CC'd).

Cheers, Andreas
======================= netconsole-2.4.8-mac.diff =====================
--- linux/drivers/net/netconsole.c.orig Thu Sep 27 10:11:27 2001
+++ linux/drivers/net/netconsole.c Thu Sep 27 17:13:24 2001
@@ -219,20 +219,10 @@
 }
 
 static char *dev;
-static int target_eth_byte0 = 255;
-static int target_eth_byte1 = 255;
-static int target_eth_byte2 = 255;
-static int target_eth_byte3 = 255;
-static int target_eth_byte4 = 255;
-static int target_eth_byte5 = 255;
+static char *target_mac;
 
 MODULE_PARM(target_ip, "i");
-MODULE_PARM(target_eth_byte0, "i");
-MODULE_PARM(target_eth_byte1, "i");
-MODULE_PARM(target_eth_byte2, "i");
-MODULE_PARM(target_eth_byte3, "i");
-MODULE_PARM(target_eth_byte4, "i");
-MODULE_PARM(target_eth_byte5, "i");
+MODULE_PARM(target_mac, "s");
 MODULE_PARM(source_port, "h");
 MODULE_PARM(target_port, "h");
 MODULE_PARM(dev, "s");
@@ -267,8 +257,8 @@
                 printk(KERN_ERR "netconsole: network device %s has no local address, aborting.\n", dev);
                 return -1;
         }
-#define IP(x) ((char *)&source_ip)[x]
- printk(KERN_INFO "netconsole: using source IP %i.%i.%i.%i\n",
+#define IP(x) ((unsigned char *)&source_ip)[x]
+ printk(KERN_INFO "netconsole: using source IP %u.%u.%u.%u\n",
                 IP(3), IP(2), IP(1), IP(0));
 #undef IP
         source_ip = htonl(source_ip);
@@ -276,8 +266,8 @@
                 printk(KERN_ERR "netconsole: target_ip parameter not specified, aborting.\n");
                 return -1;
         }
-#define IP(x) ((char *)&target_ip)[x]
- printk(KERN_INFO "netconsole: using target IP %i.%i.%i.%i\n",
+#define IP(x) ((unsigned char *)&target_ip)[x]
+ printk(KERN_INFO "netconsole: using target IP %u.%u.%u.%u\n",
                 IP(3), IP(2), IP(1), IP(0));
 #undef IP
         target_ip = htonl(target_ip);
@@ -294,18 +284,26 @@
         printk(KERN_INFO "netconsole: using target UDP port: %i\n", target_port);
         target_port = htons(target_port);
 
- daddr[0] = target_eth_byte0;
- daddr[1] = target_eth_byte1;
- daddr[2] = target_eth_byte2;
- daddr[3] = target_eth_byte3;
- daddr[4] = target_eth_byte4;
- daddr[5] = target_eth_byte5;
-
- if ((daddr[0] & daddr[1] & daddr[2] & daddr[3] & daddr[4] & daddr[5]) == 255)
- printk(KERN_INFO "netconsole: using broadcast ethernet frames to send packets.\n");
- else
- printk(KERN_INFO "netconsole: using target ethernet address %02x:%02x:%02x:%02x:%02x:%02x.\n", daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
-
+ if (target_mac) {
+ char *ptr = target_mac;
+ int i;
+
+ printk(KERN_INFO "netconsole: using target ethernet MAC: %s\n",
+ target_mac);
+ for (i = 0; i < 6 && ptr; i++) {
+ int val;
+ char *sep;
+ val = simple_strtoul(ptr, &sep, 16);
+ if (sep != ptr) {
+ daddr[i] = val;
+ ptr = *sep ? sep + 1 : NULL;
+ }
+ }
+ } else
+ printk(KERN_INFO "netconsole: using broadcast ethernet MAC.\n");
+
         netconsole_dev = ndev;
 #define STARTUP_MSG "[...network console startup...]\n"
         write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
===================== netconsole-server.diff =============================
--- netconsole-client/netconsole-server.orig Thu Sep 27 00:32:50 2001
+++ netconsole-client/netconsole-server Thu Sep 27 17:22:55 2001
@@ -30,9 +30,11 @@
 
 while [ $# -ge 1 ]; do case $1 in
         -b) NOMAC=1 ;;
- -d) DEV=$2; shift ;;
- -m) MAC=$2; shift ;;
- -p) PORT=$2; shift ;;
+ -d|--device) DEV=$2; shift ;;
+ -m|--mac) MAC=$2; shift ;;
+ -p|--port) PORT=$2; shift ;;
+ --client) TGT=`echo $2| sed "s/:.*//"`;
+ TPORT=`echo $2 | sed "s/.*://"`; shift ;;
         *:*) TGT=`echo $1 | sed "s/:.*//"`; TPORT=`echo $1 | sed "s/.*://"` ;;
         *) TGT=$1 ;;
         esac
@@ -65,16 +67,9 @@
                 echo "$prog: $DEV must be an ethernet interface" 1>&2 && usage
                 
         IPHEX=`dquad_to_hex $IPADDR`
- echo $MAC | sed "s/:/ /g" | { read M0 M1 M2 M3 M4 M5;
- if [ -z "$NOMAC" ]; then
- TGTMAC="target_eth_byte0=0x$M0 target_eth_byte1=0x$M1 \
- target_eth_byte2=0x$M2 target_eth_byte3=0x$M3 \
- target_eth_byte4=0x$M4 target_eth_byte5=0x$M5"
- fi
- echo dev=$DEV target_ip=$IPHEX \
- source_port=$PORT target_port=$TPORT $TGTMAC
- /sbin/insmod netconsole dev=$DEV target_ip=$IPHEX \
- source_port=$PORT target_port=$TPORT $TGTMAC
- }
+ [ -z "$NOMAC" ] && TGTMAC="target_mac=$MAC"
+ echo dev=$DEV target_ip=$IPHEX \
+ source_port=$PORT target_port=$TPORT $TGTMAC
+ insmod netconsole dev=$DEV target_ip=$IPHEX \
+ source_port=$PORT target_port=$TPORT $TGTMAC
 }
-
===================== netconsole-client.diff =============================
--- netconsole-client/netconsole-client.c.orig Thu Sep 27 08:32:31 2001
+++ netconsole-client/netconsole-client.c Thu Sep 27 16:07:39 2001
@@ -17,47 +17,59 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <syslog.h>
 
 #define NETCONSOLE_VERSION 0x01
 
 #define BUFLEN 10000
 
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
 int main (int argc, char **argv)
 {
         struct sockaddr_in saddr, caddr;
         int udp_socket;
- unsigned char buf[BUFLEN];
- int len, port;
+ unsigned char buf[BUFLEN], sysbuf[BUFLEN];
+ unsigned int sysoff = 0;
+ int len, port = 6666;
         struct sockaddr_in addr;
         int addr_len = sizeof(addr);
+ int noserver = 1;
 
         memset(&addr, 0, addr_len);
         memset(&saddr, 0, addr_len);
         memset(&caddr, 0, addr_len);
 
- if (argc != 7) {
- fprintf(stderr, "usage: netconsole-client -server <IP> -client <IP> -port <port>\n");
+ if (argc != 3 && argc != 5 && argc != 7) {
+ fprintf(stderr, "usage: netconsole-client --client <IP> [--port <port> [--server <IP>]]\n");
                 exit(-1);
         }
- port = atol(argv[6]);
- printf("displaying netconsole output from server %s, client %s, UDP port %d.\n", argv[2], argv[4], port);
+ if (argc > 4)
+ port = atol(argv[4]);
+ printf("listening on interface %s:%d for server %s:%d.\n", argv[2], port, argc > 6 ? argv[6] : "ANY", port);
 
 
         udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
 
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(port);
- saddr.sin_addr.s_addr = inet_addr(argv[2]);
-
         caddr.sin_family = AF_INET;
         caddr.sin_port = htons(port);
- caddr.sin_addr.s_addr = inet_addr(argv[4]);
+ caddr.sin_addr.s_addr = inet_addr(argv[2]);
+
+ if (argc > 5) {
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = htons(port);
+ saddr.sin_addr.s_addr = inet_addr(argv[6]);
+ noserver = 0;
+ }
 
         if (bind(udp_socket, (struct sockaddr *)&caddr, sizeof(caddr))) {
                 perror("could not bind UDP socket!\n");
                 exit(-1);
         }
 
+ openlog("netconsole", 0, LOG_KERN);
         while (1) {
                 len = recvfrom(udp_socket, buf, BUFLEN, 0, (struct sockaddr *)&addr, &addr_len);
                 if (len <= 0) {
@@ -65,10 +77,15 @@
                         exit(-1);
                 }
                 buf[len] = 0;
- if (!memcmp(&addr, &saddr, addr_len)) {
- unsigned int offset;
+ if (noserver || !memcmp(&addr, &saddr, addr_len)) {
+ unsigned int offset, skip;
+ unsigned int priority = LOG_WARNING, new_priority;
+ unsigned char *nl;
+
                         if (buf[0] != NETCONSOLE_VERSION) {
- printf("[netconsole server has version %d, client supports only version %d! exiting.]\n", buf[0], NETCONSOLE_VERSION);
+ printf("[netconsole server has version %d, "
+ "client supports only version %d! "
+ "exiting.]\n", *buf, NETCONSOLE_VERSION);
                                 exit(-1);
                         }
 
@@ -76,10 +93,42 @@
                         offset = (offset << 8) | buf[2];
                         offset = (offset << 8) | buf[3];
                         offset = (offset << 8) | buf[4];
+ skip = 5;
 
- printf("(%d): %s", offset, buf+5);
+ printf("%s", buf + skip);
                         fflush(stdout);
+ if (sysoff == 0 &&
+ sscanf(buf + skip, "<%d>", &new_priority) == 1) {
+ if (new_priority <= LOG_DEBUG) {
+ priority = new_priority;
+ skip += 3;
+ }
+ }
+ while ((nl = strchr(buf + skip, '\n'))) {
+ int used, left;
+
+ used = (nl - (buf + skip)) + 1;
+ left = sizeof(sysbuf) - sysoff - 1;
+
+ strncat(sysbuf + sysoff, buf + skip,
+ min(used, left));
+ /* FIXME: need to print source hostname/IP */
+ syslog(priority, "%s", sysbuf);
+ sysbuf[(sysoff = 0)] = '\0';
+ skip += min(used, left);
+ }
+ if (buf[skip]) {
+ strncat(sysbuf + sysoff, buf + skip,
+ sizeof(sysbuf) - sysoff - 1);
+ sysoff += strlen(buf + skip);
+ if (sysoff >= sizeof(sysbuf)) {
+ syslog(priority, "%s", sysbuf);
+ sysbuf[(sysoff = 0)] = '\0';
+ }
+ }
+
                 }
         }
+ closelog();
         return 0;
 }
========================= 8139too-poll.diff ==============================
--- linux/drivers/net/8139too.c.orig Tue Jul 31 15:15:28 2001
+++ linux/drivers/net/8139too.c Thu Sep 27 10:15:59 2001
@@ -619,6 +619,9 @@
 static void rtl8139_init_ring (struct net_device *dev);
 static int rtl8139_start_xmit (struct sk_buff *skb,
                                struct net_device *dev);
+#ifdef HAVE_POLL_CONTROLLER
+static void rtl8139_poll (struct net_device *dev);
+#endif
 static void rtl8139_interrupt (int irq, void *dev_instance,
                                struct pt_regs *regs);
 static int rtl8139_close (struct net_device *dev);
@@ -965,6 +968,9 @@
         dev->get_stats = rtl8139_get_stats;
         dev->set_multicast_list = rtl8139_set_rx_mode;
         dev->do_ioctl = netdev_ioctl;
+#ifdef HAVE_POLL_CONTROLLER
+ dev->poll_controller = rtl8139_poll;
+#endif
         dev->tx_timeout = rtl8139_tx_timeout;
         dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -2201,6 +2207,20 @@
         return 0;
 }
 
+
+#ifdef HAVE_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void rtl8139_poll(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ rtl8139_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
 
 static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
 {

--
Andreas Dilger  \ "If a man ate a pound of pasta and a pound of antipasto,
                 \  would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/               -- Dogbert

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Sep 30 2001 - 21:01:00 EST