Code: Alles auswählen
diff -Naur /tmp/linux-2.4.27/arch/ppc/8xx_io/netconsole.c linux-2.4.27/arch/ppc/8xx_io/netconsole.c
--- /tmp/linux-2.4.27/arch/ppc/8xx_io/netconsole.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.27/arch/ppc/8xx_io/netconsole.c 2005-04-18 17:51:17.000000000 +0200
@@ -0,0 +1,498 @@
+/*
+ * linux/drivers/net/netconsole.c
+ *
+ * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
+ *
+ * This file contains the implementation of an IRQ-safe, crash-safe
+ * kernel console implementation that outputs kernel messages to the
+ * network.
+ *
+ * Modification history:
+ *
+ * 2001-09-17 started by Ingo Molnar.
+ * 2003-08-11 2.6 port by Matt Mackall
+ * simplified options
+ * added TLAN
+ * works non-modular
+ * 2005-04-02 modified as backport for kernel 2.4
+ * works as /dev/console now
+ */
+
+/****************************************************************
+ * 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 2, 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+#include <linux/console.h>
+#include <linux/smp_lock.h>
+#include <linux/netdevice.h>
+#include <linux/tty_driver.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/inetdevice.h>
+#include <linux/delay.h>
+
+static struct net_device *netconsole_dev;
+static kdev_t netconsole_console_device(struct console *c);
+
+static u16 source_port=6665, target_port=6666;
+static u32 source_ip=0x00000000, target_ip=0xFFFFFFFF;
+static unsigned char daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
+//static unsigned char daddr[6] = {0x00, 0x50, 0xDA, 0x4C, 0x61, 0x36} ;
+
+
+#define NETCONSOLE_VERSION 0x01
+#define HEADER_LEN 5
+
+#define MAX_UDP_CHUNK 1460
+#define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
+
+/*
+ * We maintain a small pool of fully-sized skbs,
+ * to make sure the message gets out even in
+ * extreme OOM situations.
+ */
+#define MAX_NETCONSOLE_SKBS 32
+
+static spinlock_t netconsole_lock = SPIN_LOCK_UNLOCKED;
+static int nr_netconsole_skbs;
+static struct sk_buff *netconsole_skbs;
+
+#define MAX_SKB_SIZE \
+ (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
+ sizeof(struct iphdr) + sizeof(struct ethhdr))
+
+static void __refill_netconsole_skbs(void)
+{
+ struct sk_buff *skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&netconsole_lock, flags);
+ while (nr_netconsole_skbs < MAX_NETCONSOLE_SKBS) {
+ skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
+ if (!skb)
+ break;
+ if (netconsole_skbs)
+ skb->next = netconsole_skbs;
+ else
+ skb->next = NULL;
+ netconsole_skbs = skb;
+ nr_netconsole_skbs++;
+ }
+ spin_unlock_irqrestore(&netconsole_lock, flags);
+}
+
+static struct sk_buff * get_netconsole_skb(void)
+{
+ struct sk_buff *skb;
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&netconsole_lock, flags);
+ skb = netconsole_skbs;
+ if (skb)
+ netconsole_skbs = skb->next;
+ skb->next = NULL;
+ nr_netconsole_skbs--;
+ spin_unlock_irqrestore(&netconsole_lock, flags);
+
+ return skb;
+}
+
+static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int offset;
+
+static void send_netconsole_skb(struct net_device *dev, const char *msg, unsigned int msg_len)
+{
+ int total_len, eth_len, ip_len, udp_len;
+ unsigned long flags;
+ struct sk_buff *skb;
+ struct udphdr *udph;
+ struct iphdr *iph;
+ struct ethhdr *eth;
+
+ udp_len = msg_len + HEADER_LEN + sizeof(*udph);
+ ip_len = eth_len = udp_len + sizeof(*iph);
+ total_len = eth_len + ETH_HLEN;
+
+ if (nr_netconsole_skbs < MAX_NETCONSOLE_SKBS)
+ __refill_netconsole_skbs();
+
+ skb = alloc_skb(total_len, GFP_ATOMIC);
+ if (!skb) {
+ skb = get_netconsole_skb();
+ if (!skb)
+ /* tough! */
+ return;
+ }
+
+ atomic_set(&skb->users, 1);
+ skb_reserve(skb, total_len - msg_len - HEADER_LEN);
+ skb->data[0] = NETCONSOLE_VERSION;
+
+ spin_lock_irqsave(&sequence_lock, flags);
+ put_unaligned(htonl(offset), (u32 *) (skb->data + 1));
+ offset += msg_len;
+ spin_unlock_irqrestore(&sequence_lock, flags);
+
+ memcpy(skb->data + HEADER_LEN, msg, msg_len);
+ skb->len += msg_len + HEADER_LEN;
+
+ udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
+ udph->source = source_port;
+ udph->dest = target_port;
+ udph->len = htons(udp_len);
+ udph->check = 0;
+
+ iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
+
+ iph->version = 4;
+ iph->ihl = 5;
+ iph->tos = 0;
+ iph->tot_len = htons(ip_len);
+ iph->id = 0;
+ iph->frag_off = 0;
+ iph->ttl = 64;
+ iph->protocol = IPPROTO_UDP;
+ iph->check = 0;
+ iph->saddr = source_ip;
+ iph->daddr = target_ip;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+
+ eth->h_proto = htons(ETH_P_IP);
+ memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+ memcpy(eth->h_dest, daddr, dev->addr_len);
+
+repeat:
+ spin_lock(&dev->xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
+
+ if (netif_queue_stopped(dev)) {
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
+
+ dev->poll_controller(dev);
+ goto repeat;
+ }
+
+ dev->hard_start_xmit(skb, dev);
+
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->xmit_lock);
+}
+
+static void write_netconsole_msg(struct console *con, const char *msg, unsigned int msg_len)
+{
+ int len, left;
+ struct net_device *dev;
+
+ dev = netconsole_dev;
+ if (!dev)
+ return;
+
+ if (dev->poll_controller && netif_running(dev)) {
+ unsigned long flags;
+
+ __save_flags(flags);
+ local_irq_disable();
+ left = msg_len;
+repeat:
+ if (left > MAX_PRINT_CHUNK)
+ len = MAX_PRINT_CHUNK;
+ else
+ len = left;
+ send_netconsole_skb(dev, msg, len);
+ msg += len;
+ left -= len;
+ if (left)
+ goto repeat;
+ local_irq_restore(flags);
+ }
+}
+
+static char dev_name[16]="eth0";
+static char config[256];
+//module_param_string(netconsole, config, 256, 0);
+MODULE_PARM(netconsole,"s");
+MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]\n");
+
+static kdev_t netconsole_console_device(struct console *c)
+{
+ return MKDEV(TTY_MAJOR,63);
+}
+
+static int netconsole_console_setup(struct console *cons, char *str)
+{
+ return 0;
+}
+
+static struct console netconsole =
+ { name: "netc",
+ write: write_netconsole_msg,
+ device: netconsole_console_device,
+ flags: CON_ENABLED
+ };
+
+//setup: netconsole_console_setup,
+
+
+
+static int option_setup(char *opt)
+{
+ char *cur=opt, *delim;
+ int a,b,c,d;
+
+ printk(KERN_INFO "netconsole options: \"%s\"\n", opt);
+
+ if(*cur != '@') {
+ /* src port */
+ if ((delim = strchr(cur, '@')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ source_port=simple_strtol(cur, 0, 10);
+ cur=delim;
+ }
+ cur++;
+ printk(KERN_INFO "netconsole: source port %d\n", source_port);
+
+ if(*cur != '/') {
+ /* src ip */
+ if ((delim = strchr(cur, '.')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ a=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+ if ((delim = strchr(cur, '.')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ b=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+ if ((delim = strchr(cur, '.')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ c=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+ if ((delim = strchr(cur, '/')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ d=simple_strtol(cur, 0, 10);
+ cur=delim;
+
+ source_ip=(a<<24)+(b<<16)+(c<<8)+(d);
+#define IP(x) ((unsigned char *)&source_ip)[x]
+ printk(KERN_INFO "netconsole: source IP %u.%u.%u.%u\n",
+ IP(3), IP(2), IP(1), IP(0));
+#undef IP
+ }
+ cur++;
+
+ if ( *cur != '*') {
+ /* parse out dev name */
+ if ((delim = strchr(cur, '*')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ strncpy(dev_name, cur, sizeof(dev_name));
+ cur=delim;
+ }
+ cur++;
+
+ printk(KERN_INFO "netconsole: interface %s\n", dev_name);
+
+ if ( *cur != '@' ) {
+ /* dst port */
+ if ((delim = strchr(cur, '@')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ target_port=simple_strtol(cur, 0, 10);
+ cur=delim;
+ }
+ cur++;
+ printk(KERN_INFO "netconsole: target port %d\n", target_port);
+
+ /* dst ip */
+ if ((delim = strchr(cur, '.')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ a=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+ if ((delim = strchr(cur, '.')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ b=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+ if ((delim = strchr(cur, '.')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ c=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+ if ((delim = strchr(cur, '/')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ d=simple_strtol(cur, 0, 10);
+ cur=delim+1;
+
+ target_ip=(a<<24)+(b<<16)+(c<<8)+(d);
+
+#define IP(x) ((unsigned char *)&target_ip)[x]
+ printk(KERN_INFO "netconsole: target IP %u.%u.%u.%u\n",
+ IP(0), IP(1), IP(2), IP(3));
+#undef IP
+
+ if( *cur != 0 )
+ {
+ /* MAC address */
+ if ((delim = strchr(cur, ':')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ daddr[0]=simple_strtol(cur, 0, 16);
+ cur=delim+1;
+ if ((delim = strchr(cur, ':')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ daddr[1]=simple_strtol(cur, 0, 16);
+ cur=delim+1;
+ if ((delim = strchr(cur, ':')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ daddr[2]=simple_strtol(cur, 0, 16);
+ cur=delim+1;
+ if ((delim = strchr(cur, ':')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ daddr[3]=simple_strtol(cur, 0, 16);
+ cur=delim+1;
+ if ((delim = strchr(cur, ':')) == NULL)
+ goto parse_failed;
+ *delim=0;
+ daddr[4]=simple_strtol(cur, 0, 16);
+ cur=delim+1;
+ daddr[5]=simple_strtol(cur, 0, 16);
+ }
+
+ printk(KERN_INFO "netconsole: target ethernet address "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
+
+ return 0;
+
+ parse_failed:
+ printk(KERN_INFO "netconsole: couldn't parse config at %s!\n",cur);
+ return -1;
+}
+
+__setup("netconsole=", option_setup);
+
+static int init_netconsole(void)
+{
+ struct net_device *ndev = NULL;
+ struct in_device *in_dev;
+ int ret;
+
+ if(strlen(config))
+ {
+ ret=option_setup(config);
+ if(ret!=0)
+ {
+ return ret;
+ }
+ }
+/* else if (strlen(netconsole))
+ {
+ ret=option_setup(netconsole);
+ if(ret!=0)
+ {
+ return ret;
+ }
+ }
+*/
+ // this will be valid once the device goes up.
+ if (*dev_name != 0)
+ ndev = dev_get_by_name(dev_name);
+ if (!ndev) {
+ printk(KERN_ERR "netconsole: %s doesn't exist, aborting.\n",
+ dev_name);
+ return -1;
+ }
+ if (!ndev->poll_controller) {
+ printk(KERN_ERR "netconsole: %s's network driver does not"
+ " implement netlogging yet, aborting.\n", dev_name);
+ return -1;
+ }
+ in_dev = in_dev_get(ndev);
+ if (!in_dev) {
+ printk(KERN_ERR "netconsole: network device %s is not an"
+ " IP protocol device, winging it.\n", dev_name);
+ }
+/*
+ if (!source_ip) {
+ source_ip = ntohl(in_dev->ifa_list->ifa_local);
+
+ if(!source_ip) {
+ printk(KERN_ERR "netconsole: network device %s has no"
+ " local address, aborting.\n", dev_name);
+ return -1;
+ }
+
+#define IP(x) ((unsigned char *)&source_ip)[x]
+ printk(KERN_INFO "netconsole: source IP %u.%u.%u.%u\n",
+ IP(0), IP(1), IP(2), IP(3));
+#undef IP
+ }
+*/
+ source_ip = htonl(source_ip);
+ source_port = htons(source_port);
+ target_ip = htonl(target_ip);
+ target_port = htons(target_port);
+
+ netconsole_dev = ndev;
+#define STARTUP_MSG "[...network console startup...]\n"
+ write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
+
+ register_console(&netconsole);
+ printk(KERN_INFO "netconsole: network logging started\n");
+
+ return 0;
+}
+
+static void cleanup_netconsole(void)
+{
+ printk(KERN_INFO "netconsole: network logging shut down.\n");
+ unregister_console(&netconsole);
+
+#define SHUTDOWN_MSG "[...network console shutdown...]\n"
+ write_netconsole_msg(NULL, SHUTDOWN_MSG, strlen(SHUTDOWN_MSG));
+ netconsole_dev = NULL;
+}
+
+module_init(init_netconsole);
+module_exit(cleanup_netconsole);
+
+int dummy = MAX_SKB_SIZE;
diesen ganzen diffs wendest du an, aber halt auf kernel 2.4.31 anstelle 2.4.27